我有以下项目结构
--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:没有名为"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的每台机器来说,它会有所不同。
当我遇到这个问题时,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
如果设置正确,您可以
$ pip install -e .
从myproj/
目录中。然后在env.py
中,您将导入如下Base
:
from myapp.models import Base
现在有一个漂亮的方法:https://github.com/sqlalchemy/alembic/commit/d6b0c1af3df98b50c6ec52781aa411592c4e0c32
"...默认的"alembic.ini"文件包含一个指令prepend_sys_path = .
以便本地路径也在sys.path
中。
当从 Python 中的文件加载模块时,__file__
设置为其路径。然后,您可以将其与其他函数一起使用,以查找文件所在的目录。
在 alembic/env.py 文件中添加以下行以解决 ModuleNotFoundError
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
我找到了以下适用于 Linux 的解决方案,我觉得这很容易。 按以下方式运行 cmd:
PYTHONPATH={your python path} {your alembic cmd}
我将alembic
作为python模块运行,例如:
python3 -m alembic.config upgrade head
我其次@Abhishek Dhotre的anwer,因为这种方法对于开发人员可能拥有的各种项目结构都更通用,就我而言,当我运行uvicorn main:app --reload
我得到No module named app
。我通过在env.py中包含sys.path.append(path_to_app)
来解决它,其中path_to_app相对于env.py的位置,如下所示:
env.py
import sys
import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
APP_DIR = os.path.join(BASE_DIR, '../app')
sys.path.append(APP_DIR)