我有一个项目,我想这样构建:
myproject
├── api
│ ├── __init__.py
│ └── api.py
├── backend
│ ├── __init__.py
│ └── backend.py
├── models
│ ├── __init__.py
│ └── some_model.py
└── __init__.py
现在,我想在
some_model.py
和 api.py
中导入模块 backend.py
。我该如何正确地做到这一点?
我尝试过:
from models import some_model
但是失败了
ModuleNotFoundError: No module named 'models'
。
我也尝试过:
from ..models import some_model
这给了我
ValueError: attempted relative import beyond top-level package
。
我在这里做错了什么?如何从其他目录(不是子目录)导入文件?
首先,这个导入声明:
from models import some_model
应该命名空间:
# in myproject/backend/backend.py or myproject/api/api.py
from myproject.models import some_model
然后您需要将包含
myproject
的目录(我们称之为/path/to/parent
)放入sys.path
列表中。您可以通过设置环境变量来临时执行此操作:
export PYTHONPATH=/path/to/parent
或者,最好,您可以通过编写
setup.py
文件并安装包来完成。请遵循 PyPA 包装指南。编写完 setup.py
文件后,在同一目录中执行此命令以在 sys.path
中设置正确的条目:
pip install --editable .
不幸的是,只有当您的文件位于系统路径中时,Python 才会找到您的文件。但不要害怕!有办法解决这个问题!
使用 python 的
sys
模块,我们可以在 Python 运行时向路径添加一个目录,仅用于程序的当前运行。这不会影响以后运行的任何其他 Python 程序。
您可以通过以下方式做到这一点:
import sys
import os
sys.path.insert(0, os.path.abspath('relative/path/to/application/folder'))
import [file]
在导入文件之前导入 sys 并设置目录路径非常重要。
如果您的库不靠近当前目录,绝对路径可能会更简单:
import sys
sys.path.insert(0, '/absolute/path/to/application/folder'))
import [file]
是的,这是一个黑客行为。但作为短期解决方法,它可能会有所帮助。
我会提出两种方法:
通过绝对导入简单导入
some_model
:
from myproject.models import some_model
请注意,
myproject
应被视为一个模块(即具有__init__.py
)
或者
您可以将之前的路径添加到我在此类并行级别模块中使用的
sys.path
:
import sys
sys.path.append('../')
from models import some_model