带有 asyncpg 的 FastAPI 项目具有来自 psycopg2 的依赖项,这会导致错误 ModuleNotFoundError:没有名为 'psycopg2' 的模块

问题描述 投票:0回答:1

我有一个 FastAPI 项目,它使用

asyncpg
连接到 PostgreSQL。 我使用
poetry
,以下是我的
pyproject.toml
文件。

[tool.poetry]
name = "my_project"
version = "0.1.0"
description = ""
authors = ["Me"]
[tool.poetry.dependencies]
python = "^3.10"
fastapi = "^0.104.0"
uvicorn = "^0.23.2"
sqlmodel = "^0.0.8"
asyncpg = "^0.28.0"
greenlet = "^3.0.0"
pytest = "^7.4.2"
pytest-asyncio = "^0.21.1"
httpx = "^0.25.0"
passlib = "^1.7.4"
python-jose = "^3.3.0"
python-multipart = "^0.0.6"
bcrypt = "^4.0.1"
black = "^23.10.1"
bandit = "^1.7.5"
alembic = "^1.12.1"
python-json-logger = "^2.0.7"
coverage = "^7.4.0"
pytest-cov = "^4.1.0"
cryptography = "^42.0.4"
python-dotenv = "^1.0.1"

[tool.poetry.dev-dependencies]

但是,我注意到,当我运行

poetry install
时,生成的
poetry.lock
文件在长文件的两部分中具有来自
psycopg2
的依赖项,我不打算在这里全部过去。

mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"]
mysql-connector = ["mysql-connector-python"]
oracle = ["cx-oracle (>=7)", "cx-oracle (>=7,<8)"]
postgresql = ["psycopg2 (>=2.7)"]
postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"]
postgresql-psycopg2binary = ["psycopg2-binary"]
postgresql-psycopg2cffi = ["psycopg2cffi"]
pymysql = ["pymysql", "pymysql (<1)"]
sqlcipher = ["sqlcipher3-binary"]

尽管使用了

asyncpg
,但仍然依赖于非异步
psycopg2
。 此外,当我为我的项目构建 Docker 容器时,这会导致另一个问题。 以下是我正在使用的
Dockerfile

# Base image
FROM python:3.10 AS python-base

# Environment variables
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PIP_NO_CACHE_DIR=off \
    PIP_DISABLE_PIP_VERSION_CHECK=on \
    PIP_DEFAULT_TIMEOUT=100 \
    POETRY_HOME="/opt/poetry" \
    POETRY_VIRTUALENVS_IN_PROJECT=true \
    POETRY_NO_INTERACTION=1 \
    PYSETUP_PATH="/opt/pysetup" \
    VENV_PATH="/opt/pysetup/.venv"

ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"

# Builder stage
FROM python-base AS builder-base
RUN buildDeps="build-essential" \
    && apt-get update \
    && apt-get install --no-install-recommends -y \
        curl \
        build-essential \
    && apt-get install -y --no-install-recommends "$buildDeps" \
    && apt-get install -y iputils-ping \
    && apt-get install -y dnsutils \
    && apt-get install -y wget \
    && rm -rf /var/lib/apt/lists/*

WORKDIR $PYSETUP_PATH
COPY poetry.lock pyproject.toml ./

# Use the same version of Poetry as used locally
ENV POETRY_VERSION=1.5.1
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN curl -sSL https://install.python-poetry.org | POETRY_HOME=${POETRY_HOME} python3 - --version ${POETRY_VERSION} && \
    chmod a+x /opt/poetry/bin/poetry

RUN poetry config virtualenvs.in-project false
RUN poetry install --no-interaction --no-dev

# Development stage
FROM python-base AS development
ENV FASTAPI_ENV=development

COPY --from=builder-base $POETRY_HOME $POETRY_HOME
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH

WORKDIR $PYSETUP_PATH
RUN poetry install

WORKDIR /app
COPY . .

EXPOSE 8000
CMD ["poetry", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

这是

docker-compose.yml
的一个。

version: '3.8'

services:
  web:
    build: .
    env_file:
      - .env
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: postgres:13
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: mydatabase
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

运行的结果

docker-compose up 
我收到以下错误

Traceback (most recent call last):
  File "/opt/pysetup/.venv/bin/uvicorn", line 8, in <module>
    sys.exit(main())
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/uvicorn/main.py", line 416, in main
    run(
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/uvicorn/main.py", line 587, in run
    server.run()
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/uvicorn/server.py", line 61, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "/usr/local/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/uvicorn/server.py", line 68, in serve
    config.load()
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/uvicorn/config.py", line 467, in load
    self.loaded_app = import_from_string(self.app)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/uvicorn/importer.py", line 24, in import_from_string
    raise exc from None
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/uvicorn/importer.py", line 21, in import_from_string
    module = importlib.import_module(module_str)
  File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/app/app/main.py", line 9, in <module>
    from app.router.api_v1.endpoints import api_router
  File "/app/app/router/api_v1/endpoints.py", line 3, in <module>
    from app.login.api import router as login_router
  File "/app/app/login/api.py", line 9, in <module>
    from app.core.security import create_access_token
  File "/app/app/core/security.py", line 15, in <module>
    from app.core.db import get_async_session
  File "/app/app/core/db.py", line 14, in <module>
    async_engine = create_async_engine(db_connection_str, echo=True, future=True)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/sqlalchemy/ext/asyncio/engine.py", line 43, in create_async_engine
    sync_engine = _create_engine(*arg, **kw)
  File "<string>", line 2, in create_engine
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/sqlalchemy/util/deprecations.py", line 309, in warned
    return fn(*args, **kwargs)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/sqlalchemy/engine/create.py", line 548, in create_engine
    dbapi = dialect_cls.dbapi(**dbapi_args)
  File "/opt/pysetup/.venv/lib/python3.10/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py", line 811, in dbapi
    import psycopg2
ModuleNotFoundError: No module named 'psycopg2'

我用

poetry show—-tree | grep psycopg2
检查了是否有任何已安装的软件包依赖于 psycopg2,结果没有。

poetry show --tree | grep postgresql

相同

我还尝试删除

venv
并从头开始重新创建所有内容,但没有不同的结果。

我需要将

psycopg2
添加到依赖项列表中吗?如果是,为什么有必要? 此外,如果我安装它,我收到以下错误

sqlalchemy.exc.InvalidRequestError: The asyncio extension requires an async driver to be used. The loaded 'psycopg2' is not async.
docker docker-compose fastapi psycopg2 asyncpg
1个回答
0
投票

我设法找到了问题。 在

.env
文件中,用于连接数据库的字符串是

DB_ASYNC_TEST_CONNECTION_STR="postgresql://postgres:pass/db_tests" 

将其更改为

postgresql+asyncpg://
解决了错误 `ModuleNotFoundError:没有名为“psycopg2”的模块

尽管如此,在

poetry.lock
中,仍然存在来自
psycopg2.
的依赖关系 `

© www.soinside.com 2019 - 2024. All rights reserved.