我有一个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
...
我使用以下命令从Venv激活项目目录运行项目:
(venv)$ python src/scripts/script.py
脚本运行但在退出之前发出以下错误:
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作为工作目录?
答案 0 :(得分:18)
基本上,当你直接执行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.py
是src
模块的入口点(例如,也许它是主程序)。如果这是真的,那么您可以通过将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
作为{{1}的一部分像这样的模块:
src
因为你告诉python你正在运行哪个模块($ python -m src.scripts.script
),它将在路径中。因此,src
会知道它是script.py
的子模块,然后才能从src
导入。
在这种情况下要小心 - 如果src
导入src
中的内容,则可能会创建循环导入。
作为这两种方法的替代方法,您可以直接在src.scripts.script
修改sys.path
:
script.py
虽然这有效,但通常不是我的偏好。它需要import sys
sys.path.insert(0, '/path/to/Project') # location of src
确切地知道你的代码是如何布局的,如果另一个python程序试图导入script.py
,可能会导致导入混乱。
答案 1 :(得分:0)
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
答案 2 :(得分:0)
另一种解决方案是创建文件名“ xxx(任何名称).pth”并写入项目目录(src的母亲目录)。将此文件放在“ / virtual_env / lib / pythonXX / site-packages /”中。这样,您无需在脚本中导入sys.path。
答案 3 :(得分:0)
如果在处理Pytest
或coverage
时遇到此问题。添加__init__.py
文件可以解决大多数情况。