我有以下目录结构
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
我在这里缺少什么?
答案 0 :(得分:0)
您需要先将父目录添加到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
答案 1 :(得分:0)
实际上,您的所有示例都不应该开箱即用。
让我们稍微修改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
仅sys.path
(不是当前目录)自动添加到path[0]
:
在程序启动时初始化时,此列表的第一项
的结果插入条目之前插入了脚本目录path[0]
,是包含用于调用Python解释器的脚本的目录。*如果脚本目录不可用(例如,如果以交互方式调用解释器或者从标准输入读取脚本),PYTHONPATH
是空字符串,它将Python指向当前的搜索模块目录首先 strong>。请注意,在stuff
。
因此sys.path
上没有PYTHONPATH
模块。我不确定您的环境设置,但这是在没有设置其他参数时的规范结果(例如from ..stuff import mainfile
)。
相若方式,
ValueError: Attempted relative import in non-package
将产生经典script
。您被告知您只能进行相对于实际模块的相对导入。由于..
..
内部没有引用模块(因为脚本本身就是顶层模块),因此相对导入不起作用。从Python的角度来看,脚本上方没有模块,因此project
在脚本的上下文中使用时不会引用有形的东西。
请注意,这也意味着它 not 有助于仅通过删除project/bin
标记文件将__init__.py
和-m
转换为模块。只有当脚本的父实际上是python具有概念的东西时,才可能相对导入脚本的父。
这是为什么python -m project.bin.script
命令行开关存在使得可以从命令行运行模块的原因之一。例如,给定上面的相对导入
from project.stuff import mainfile
可以解决问题,但只有从正确的目录( projectdir / ..)执行才能解决。
,问题更严重
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
:
SELECT SQL_NO_CACHE *
FROM obj
WHERE (obj__status = 2) AND (obj__obj_type__id = 59)
ORDER BY obj__title ASC
LIMIT 0, 500;