理解Python中的一系列进口

时间:2011-03-08 00:11:11

标签: python import python-3.x

我知道有几个类似的问题,但我很难理解我得到的错误,浏览文档和类似的问题还没有帮助。如果有的话,类似的问题让我觉得我正在做的事情是对的。

我有以下文件:

的src / main.py

from pack import pack

if __name__ == '__main__':
    pack.exec("Hello Universe!")

的src /包/ pack.py

import util

def exec(text):
    util.write(text)

if __name__ == '__main__':
    exec("Hello World!")

的src /包/ util.py

def write(text):
    print(text)

*的的src /包/ _ 初始化 _。PY *

EMPTY FILE

当我从python pack.py目录运行src/pack时,它可以正常工作(打印“Hello World!”)。但是,当我从python main.py目录运行src时,我得到以下异常:

Traceback (most recent call last):
  File ".../src/main.py", line 1, in <module>
    from pack import pack
  File ".../src/pack/pack.py", line 1, in <module>
    import util
ImportError: No module named util

如果我按照建议将pack.py中的导入行更改为from . import util,则实际上会出现相反的情况。 main.py成功运行,但现在pack.py失败,提升:

Traceback (most recent call last):
  File ".../src/pack/pack.py", line 1, in <module>
    from . import util
ValueError: Attempted relative import in non-package

我原以为导入是相对于当前位置的,因此你应该能够像这样构建一系列导入。对我来说,模块应该根据程序的起始位置以不同方式导入兄弟文件,这似乎很奇怪。

有人可以解释为什么这种错误以一种方式发生而不是另一种方式,并且如果有某种方式允许这种文件结构运行我是否想要从main.pypack.py运行? / p>

4 个答案:

答案 0 :(得分:6)

在这两种情况下,您都无法进行导入工作。这是因为在一种情况下,您将pack.py作为主文件运行,而在另一种情况下,您将其作为程序包的一部分运行。

当您将其作为独立脚本python pack.py运行时,“pack”目录将添加到PYTHONPATH,这意味着您可以导入其中的任何模块。因此,import util将起作用。

运行python main.py时,将src目录添加到PYTHONPATH。这意味着src中的任何模块或包,例如pack目录,现在都可以导入。因此from pack import pack。但是,要访问util.py,您现在需要执行from pack import util。正如您所注意到的,您也可以在from . import utilpack.py进行src/

但你不能同时做到这两点。 src/pack是主目录或src/pack是。

明显但错误的解决方案是让main.py将src/pack目录添加到PYTHONPATH。这将有效,但这不是一个好主意。这样做的正确方法是下定决心。 import pack是一个应该通过src/pack导入的模块,还是只是一个包含许多Python脚本的文件夹?决定! : - )

我认为在这种情况下,'显然from pack import util应该是一个模块。因此,将其视为一个模块,并确保它像模块一样可用。然后,即使将pack.py作为主脚本运行,您也可以src

你是怎么做到的?好吧,基本上你要么在你的站点包中安装pack模块,要么将export PYTHONPATH=<path>目录添加到PYTHONPATH。最后一个是你在开发过程中想要的。您可以使用{{1}}手动执行此操作,也可以让您的测试人员为您执行此操作。你没有testrunner?那么你应该,但这是另一个问题。 :)

如果您不再进行开发,请永久安装它,请查看Distribute。它包括一个testrunner。 ;)

答案 1 :(得分:4)

您的链接是python 2.7文档,但看起来您使用的是Python 3.x。

请参阅此处:http://docs.python.org/py3k/了解正确的文档。

Python 3删除隐式相对导入。也就是说,您不能再以相同的方式在同一模块中导入包。

您需要使用from . import util,这是明确的相对导入并且是允许的。 import X不再检查当前目录。相反,它只检查sys.path中的条目。这包括脚本的目录和python的标准库。

答案 2 :(得分:2)

您的包目录中缺少__init__.py。

在包目录中创建一个名为__init__.py的空文件。

答案 3 :(得分:0)

correct documentation中没有任何内容支持您的理论,即此导入形式应该有效。