蒸馏器。env.py 中的 ModuleNotFoundError

MrO*_*Sir 13 python sqlalchemy alembic

我有以下项目结构

 --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
Run Code Online (Sandbox Code Playgroud)

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

Base__init__.py模型中的文件夹

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)
Run Code Online (Sandbox Code Playgroud)

并导入这是 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
Run Code Online (Sandbox Code Playgroud)

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

ModuleNotFoundError: 没有名为“models”的模块

我该如何解决这个错误?

dar*_*all 28

问题是env.py执行时,models不在您的 中PYTHONPATH,因此无法导入。

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

import sys

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

from models import Base
Run Code Online (Sandbox Code Playgroud)

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

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

$ export PYTHONPATH='/path/to/some db/some db':$PYTHONPATH
Run Code Online (Sandbox Code Playgroud)

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

当我遇到这个问题时,SQLAlchemy 开发人员建议如果我使用pip虚拟环境,我可以在可编辑模式下安装我的项目,以便它在系统中PYTHONPATH并且 Alembic 可以从任何地方找到它。Python 打包指南中提供了更多详细信息。为此,您setup.py的项目需要一个,并且您可能希望更改项目结构,以便有一个包含models和等内容的顶级模块alchemy。例如:

myproj/
    setup.py
    alembic/
        env.py
        migrations/
    myapp/
        __init__.py
        alchemy/
            __init__.py
        models/
            __init__.py
Run Code Online (Sandbox Code Playgroud)

如果设置正确,您可以

myproj/
    setup.py
    alembic/
        env.py
        migrations/
    myapp/
        __init__.py
        alchemy/
            __init__.py
        models/
            __init__.py
Run Code Online (Sandbox Code Playgroud)

myproj/目录内部。然后env.py你会Base像这样导入:

$ pip install -e .
Run Code Online (Sandbox Code Playgroud)


小智 25

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

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

  • 这应该是最重要的答案,它仅在 Alembic 1.5.5(发布日期 2021 年 2 月 20 日)中引入。针对OP问题,解决方案是将`alembic.ini`中的密钥更改为`prepend_sys_path = ..` (4认同)

小智 6

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

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

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
Run Code Online (Sandbox Code Playgroud)