我在使用使用单独模块来构建代码的 python 包时遇到问题。包本身可以工作,但是当从另一个环境导入时会失败并出现 ModuleNotFound 错误。 结构如下:
Project-root
|
|--src/
| __init__.py
| module_a.py
| module_b.py
| module_c.py
| module_d.py
|--tests
etc.
在 module_a.py 中我有:
from module_a import function_a1,...
from module_b import function_b1,...
from module_c import function_c1,...
在 module_c 中,我导入 module_d ,如下所示:
from module_d import function_d1,...
如上所述,直接从 CLI 执行 module_a 或 module_c 按预期工作,我在测试目录中创建的单元测试也可以工作(在 sys.path.insert 的帮助下),但是如果我创建一个新环境并导入包时出现以下错误:
>>> import module_a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/<abs_path>/.venv/lib/python3.9/site-packages/module_a.py", line 22, in <module>
from module_c import function_c1, function_c2
File /<abs_path>/.venv/lib/python3.9/site-packages/module_c.py", line 9, in <module>
import module_d
ModuleNotFoundError: No module named 'module_d'
>>>
我已经用尽了如何克服这个问题的所有想法,除了将模块 c 和 d 的代码组合在一个文件中(我不想这样做),或者重新考虑流程以便从 module_a 导入所有模块。 任何如何解决这个问题的建议将不胜感激。 更新:原来是 setup.py 中 module_d 名称的输入错误。无论出于何种原因,
python setup.py install
都默默地失败了,或者我没有仔细阅读日志。
问题归结为理解导入系统和PYTHONPATH的基础知识。
当您尝试导入模块(
import module_a
)时,Python 将在 sys.path
中列出的每个目录中按顺序搜索。如果在其中一个目录中找到与名称 (module_a
)1 匹配的目录,则它会运行 __init__.py
文件。如果找到文件,它会直接转换为模块。
ImportError
时,表示 sys.path
中不存在包含所询问名称的文件/目录的目录。
您说在测试中您做了类似
sys.path.insert(0, "some/path/")
的事情,但这不是解决方案,只是一个损坏的修复。
您应该做的是设置您的
PYTHONPATH
环境变量以包含模块所在的目录,在您的情况下为 Project-root/src
。这样,就无需使用 sys.path.insert
,或在导入语句中摆弄相对/绝对路径。
创建新环境时,只需将环境变量
PYTHONPATH
设置为包含 Project-root/src
即可完成。这就是安装常规 Python 模块(库)的工作方式:它们全部放入 site-packages
中的目录中。
1:自旧的 Python 版本以来,这一点发生了变化,过去需要目录包含
__init__.py
文件,请参阅 PEP-420