sys.path
。尝试以下操作:我具有以下目录结构
project/
bin/
script
stuff/
__init__.py
mainfile.py
在脚本内部,我具有以下启用命令行执行的功能:
#!/usr/bin/env python
from stuff import mainfile
此方法有效,但我原本希望需要跳到更高的水平...
from ..stuff import mainfile
或
from project.stuff import mainfile
我在这里想念什么?
实际上,您的所有示例都不应该立即可用。
让我们稍微修改bin/script.py
:
#! /usr/bin/env python
import sys
print sys.path
from stuff import mainfile
这应该会产生类似的结果
['.../project/bin', ...]
Traceback (most recent call last):
File "bin/script.py", line 6, in <module>
from stuff import mainfile
ImportError: No module named stuff
仅the directory of the script(不是当前目录)自动添加到sys.path
:
在程序启动时初始化,此列表的第一项
path[0]
,是包含用于调用Python解释器的脚本的目录。*如果脚本目录不可用(例如,如果解释器是交互调用的,或者如果从标准输入中读取脚本,则path[0]
是空字符串,它将Python引导到首先在当前目录中搜索模块。注意,由于PYTHONPATH
的结果,在插入条目之前插入了脚本目录。因此
stuff
上没有sys.path
模块。我不确定您的环境设置如何,但这是没有设置其他参数(例如PYTHONPATH
)时的典型结果。
Similally,
from ..stuff import mainfile
将产生经典的
ValueError: Attempted relative import in non-package
。您将得知,您只能相对于实际模块进行相对导入。由于script
内部..
没有引用模块(可以说脚本本身是顶级模块),因此相对导入在这里不起作用。从Python的角度来说,脚本上方没有模块,因此..
在脚本的上下文中使用时未指的是有形的东西。
注意,这还意味着not
通过删除project
标记文件仅使project/bin
和__init__.py
成为模块本身是有帮助的。仅当脚本的父级实际上是python所理解的东西时,才可能相对导入到脚本的parent。这是原因,为什么存在-m
命令行开关,因此可以从命令行运行模块。例如,鉴于上述相对导入
python -m project.bin.script
有技巧,但仅当从正确的目录(projectdir
/ ..)执行时才可以。
该问题甚至更严重
from project.stuff import mainfile
因为当从
project
上方的目录中启动脚本时,sys.path
目录仅在project
上自动存在,因此[不指定要运行的主脚本:
cd <projectdir>/..
python -m project.bin.script
# works
cd <projectdir>
python -m bin.script
# does not work, because `sys.path` starts with <projectdir>
# and it's `stuff.mainfile` now, not `project.stuff.mainfile`.
如果要从脚本中的project
导入模块,请根据需要修复sys.path
:
import sys import os sys.path.insert(0, os.path.dirname(sys.path[0])) from stuff import mainfile
您需要先将父目录添加到sys.path
。尝试以下操作:
# This is a file in bin/ directory. this_file_path = os.path.dirname(__file__) sys.path.append(os.path.join(this_file_path, '..')) import stuff.mainfile
sys.path
。尝试以下操作: