Python 找不到我的模块

Python can't find my module

我有一个 python 项目(我在 virtualenv 中 运行)并且具有以下结构:

Project
├───.git
├───venv
└───src
    ├───__init__.py
    ├───mymodules
    │   ├───__init__.py
    │   ├───module1.py
    │   └───module2.py
    └───scripts
        ├───__init__.py
        └───script.py

script.py

import src.mymodules.module1
...

I 运行 激活了 venv 的项目,并从项目目录中使用以下命令:

(venv)$ python src/scripts/script.py

脚本 运行s 但在退出前出现以下错误:

Traceback (most recent call last):
  File "src/scripts/script.py", line 1, in <module>
    import src.mymodules.module1
ImportError: No module named src.mymodules.module1

我已经尝试 运行 宁 python shell 并尝试从那里导入模块并且它没有给出任何错误。我在 src 的每个目录中都有 _ _init__.py。 python 认为工作目录是 src/scripts 吗?为什么会发生这种情况?如果是这样,我如何才能使 src 成为工作目录?

本质上,当你直接执行 script.py 时,它不知道它是 src 的子模块的一部分,也不知道名为 src 的模块可能在哪里. python 2 或 3 都是这种情况。

如您所知,Python 根据 sys.path 的内容查找模块。为了导入任何模块,它必须位于 sys.path 中列出的目录中,或者与您正在使用的脚本位于同一目录中 运行。

当您说 python src/scripts/script.py 时,sys.path 包括 Project/src/scripts/(因为那是 script.py 所在的位置),但不包括 Project。因为 Project 不在路径中,所以无法导入该目录 (src) 中的模块。

解决这个问题:

我假设您的 script.pysrc 模块的入口点(例如,它可能是主程序)。如果这是真的,那么您可以通过将 script.py 移动到与 src:

相同的级别来修复它
Project
├───.git
├───venv
|───script.py       <--- script.py moves up here
└───src
    ├───__init__.py
    └───mymodules
        ├───__init__.py
        ├───module1.py
        └───module2.py

这样,script.py可以自由导入src中的任何内容,但src中的任何内容都不能导入script.py

如果不是这样,并且script.py确实是src的一部分,你可以使用python的-m参数来执行script.py 作为 src 模块的一部分,像这样:

$ python -m src.scripts.script

因为您已经告诉 python 您是哪个模块 运行 (src),所以它将在路径中。因此,script.py 将意识到它是 src 的子模块,然后将能够从 src 导入。

不过在这种情况下要小心 - 如果 src 中的某些内容导入 src.scripts.script,则可能会创建循环导入。


作为这两种方法的替代方法,您可以直接在 script.py 中修改 sys.path

import sys
sys.path.insert(0, '/path/to/Project') # location of src 

虽然这可行,但我通常不喜欢它。它需要 script.py 准确地知道您的代码是如何布局的,并且如果另一个 python 程序试图导入 script.py 可能会导致导入混乱。

Project
├───.git
├───venv
└───src
    ├───__init__.py
    ├───mymodules
    │   ├───__init__.py
    │   ├───module1.py
    │   └───module2.py
    └───scripts
        ├───__init__.py
        └───script.py

或者,您可以在 script.py

中导入如下内容
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__),'../../'))
import src.mymodules.module1

现在您可以从任何位置 运行 script.py 文件。

e.g :
python script.py
python /path to folder/script.py

另一个解决方案是创建文件 some_file.pth 并写入您的项目目录(您的 src 的母目录)。将此文件放在 /virtual_env/lib/pythonXX/site-packages/ 中。这样,您就不需要在脚本中导入sys.path

如果您在处理 Pytestcoverage 时遇到此问题。添加 __init__.py 文件解决了大多数情况。