蒸馏器。 env.py 中的 ModuleNotFoundError

Alembic. ModuleNotFoundError in env.py

我有 foloving 项目结构

 --some db:
        --some db:
            --alchemy:
                -- __init__.py
            --alembic:
                -- versions
                -- env.py
                -- README.py
                -- script.py
            --migrations:
                -- __init__.py
            --models:
                -- model_1
                -- model_2
                -- __init__.py

我尝试通过 alembic 自动生成迁移。

我在模型文件夹__init__.py中有Base

import sqlalchemy as sa

from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base, declared_attr


metadata = sa.MetaData()
Base = declarative_base(metadata=metadata)

并导入这是 env.py

from logging.config import fileConfig

from alembic import context
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from models import Base

config = context.config
fileConfig(config.config_file_name)
target_metadata = Base.metadata

因此,当我从 alembic 目录中的 env.py 中的模型导入 Base 并尝试生成自动迁移时,我遇到了一些错误,例如

ModuleNotFoundError: No module named 'models'

我该如何解决这个错误?

问题是执行env.py时,models不在你的PYTHONPATH中,所以无法导入。

根据您概述的项目结构,可能有点难以解决;最简单的解决方案可能是像这样在 env.py 中修改 PYTHONPATH

import sys

sys.path = ['', '..'] + sys.path[1:]

from models import Base

这会将 alembic/ 的父目录添加到您的 PYTHONPATH 以便它可以找到 models 模块。

或者,将包含模块的目录添加到 shell 中的 PYTHONPATH 环境变量中:

$ export PYTHONPATH='/path/to/some db/some db':$PYTHONPATH

此解决方案有点脆弱,因为您必须记住每次会话都执行此操作,并且对于您打算 运行 Alembic on 的每台机器,它都会有所不同。

当我 运行 进入这个问题时,SQLAlchemy 开发人员 suggested that if I was using pip and virtual environments, I could install my project in editable mode so that it's in the system PYTHONPATH and Alembic would be able to find it from anywhere. More details are available in the Python packaging guide。为此,您的项目需要一个 setup.py,并且您可能想要更改项目结构,以便有一个包含 modelsalchemy 之类的顶级模块。例如:

myproj/
    setup.py
    alembic/
        env.py
        migrations/
    myapp/
        __init__.py
        alchemy/
            __init__.py
        models/
            __init__.py

如果设置正确,您可以

$ pip install -e .

myproj/ 目录中。然后在 env.py 中,您将像这样导入 Base

from myapp.models import Base

从 Python 中的文件加载模块时,__file__ 设置为其路径。然后,您可以将其与其他函数结合使用来查找文件所在的目录。

在 alembic/env.py 文件中添加以下行以解决 ModuleNotFoundError

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

现在有一个漂亮的方法:https://github.com/sqlalchemy/alembic/commit/d6b0c1af3df98b50c6ec52781aa411592c4e0c32

”...默认的“alembic.ini”文件包含指令prepend_sys_path = .,因此本地路径也在sys.path.

我为 Linux 找到了以下解决方案,我觉得这很简单。 运行 命令为:

PYTHONPATH={your python path} {your alembic cmd}