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

bon*_*ges 3 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
Run Code Online (Sandbox Code Playgroud)

这是结构.

generator/
    __init__.py
    the_generator.py
    the_page.py
    tasks/
        __init__.py
        task_a.py
Run Code Online (Sandbox Code Playgroud)

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

aba*_*ert 9

从包中间运行脚本是一个坏主意,出于多种原因,最明显的是你遇到的那个:当你在import generator.the_generator某个地方时,generator最终成为一个包,所以绝对导入generator.the_page,或者一个相对导入,将工作正常.但是当你运行脚本时generator/the_generator.py,没有generator.the_generator,只是__main__,并且没有generator包.Python可以知道如何查找的唯一方法generator.the_page是,如果父目录generator是打开的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()
Run Code Online (Sandbox Code Playgroud)

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