我有一个python项目(我在virtualenv中运行),它具有以下结构:
Project
├───.git
├───venv
└───src
├───__init__.py
├───mymodules
│ ├───__init__.py
│ ├───module1.py
│ └───module2.py
└───scripts
├───__init__.py
└───script.py
script.朋友
import src.mymodules.module1
...
我使用以下命令激活venv并从Project目录运行项目:
(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成为工作目录?
基本上,当你直接执行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
作为src
模块的一部分,如下所示:
$ python -m src.scripts.script
因为你告诉python你正在运行哪个模块(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
虽然这有效,但通常不是我的偏好。它需要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
另一种解决方案是创建文件名'xxx(任意名称).pth'并编写项目目录(src的母目录)。将此文件放在'/ virtual_env / lib / pythonXX / site-packages /'中。这样,您就不需要在脚本中导入sys.path。