python相对导入结构

时间:2015-07-07 15:57:02

标签: python import relative

我有以下目录结构

   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

我在这里缺少什么?

2 个答案:

答案 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指向当前的搜索模块目录首先。请注意,在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;