调用子模块时出现“无模块命名”错误

时间:2013-08-28 19:03:44

标签: python python-2.7

我在使用import语句时遇到问题,因为Python报告没有名为the_page或the_generator的模块。

task_a.py包含import generator.the_page as ThePage,当作为主脚本运行时,没有问题。

the_generator.py包含import tasks.task_a,但当我将其作为主脚本运行时,python会抛出以下错误。

Traceback (most recent call last):
  File "/generator/the_generator.py", line 7, in <module>
    import tasks.tasks_a
  File "/generator/tasks/tasks_a.py", line 3, in <module>
    import generator.the_page as ThePage
ImportError: No module named the_page

这是结构。

generator/
    __init__.py
    the_generator.py
    the_page.py
    tasks/
        __init__.py
        task_a.py

也许你可以帮我解决问题。感谢您的帮助!

1 个答案:

答案 0 :(得分:8)

从包中间运行脚本是一个坏主意,原因有很多,其中最明显的是你遇到的那个:当你import generator.the_generator某个地方,generator最终作为一个包,因此绝对导入generator.the_page或相对导入将正常工作。但是当您运行脚本generator/the_generator.py时,没有generator.the_generator,只有__main__,并且没有generator个包。如果generator.the_page的父目录在generator上,那么Python可以知道如何查找sys.path的唯一方法就是{。}}。

正如你猜测的那样,你可以通过调整sys.path将相应的父目录放在那里来解决这个问题......但这也是一个坏主意。

此解决方案还存在许多其他问题。最严重的是,它很容易导致同一个模块被导入两次(因为Python无法知道两个明显不相关的名称碰巧引用同一个模块)。它也很难部署(如果它依赖于在一个包中,你就不能将脚本安装到/usr/local/bin ...),如果你的包用完了.zip或.egg等,它将无法运行


有两种标准方法可以解决这个问题。

首先,只需将脚本作为模块而不是脚本运行。在generator的父目录中,只有python -m generator.the_generator而不是python generator/the_generator.py

这样做的一个主要优点是,在正常安装的部署中,generator位于某个地方的某个地方,就像在测试中一样。

或者,创建一个与generator并排放置的脚本,并运行该脚本,而不是其中的模块。这可以像将if __name__ == '__main__':中的所有the_generator.py代码移动到函数中,然后编写两行包装一样简单:

import generator.the_generator
generator.the_generator.main()

同样,这在正常安装的部署中也同样有效。此外,这意味着该脚本可以安装到您的bin目录中,使事情变得更加轻松,就像pipipython一样。