【问题标题】:Running a module in a package, importing a subpackage在包中运行模块,导入子包
【发布时间】:2018-01-31 12:29:33
【问题描述】:

我感觉这个问题以前被问过很多次,但不知何故,似乎相关问题的答案都没有让我完全理解发生了什么。

情况:我创建了一个包,在该包内我有另一个包,我希望能够直接运行所有这些包,用于测试目的,即:

\main.py
\package_1\__init__.py
\package_1\module_1.py
\package_1\package_2\__init__.py
\package_1\package_2\module_2.py

main.py 在哪里:

from package_1.module_1 import func_1
func_1()

还有module_1.py:

from package_1.package_2.module_2 import func_2
def func_1():
    func_2()
if __name__ == "__main__":
    func_1()

还有module_2.py:

def func_2:
    print ("This works")
if __name__ == "__main__":
    func_2()

__init__.py 是空的。这允许我从根目录运行 main.py 并且它可以工作。我也可以从自己的文件夹中运行 module_2.py。但我无法运行 module_1.py,因为它抱怨没有 package_1。这是有道理的,尽管从技术上讲它本身就在 package_1 中。但是如果我删除那个前缀,它会破坏 main,这也有一定的意义。

如何解决这个问题?我尝试将 module_1.py 中的导入替换为:

import .package_2.module_2

但这给了我一个我不完全理解的错误:

ModuleNotFoundError: No module named '__main__.package_2'; '__main__' is not a package

让所有包和模块按预期工作的正确方法是什么?是否应该在 __init__.py 中解决?或者我应该简单地避免像这样嵌套包并安装它们(在提供 setup.py 之后)?

编辑:

@Blckknght 建议运行:

python -m package_1.module_1
python -m package_1.package_2.module_1

从根目录。这行得通,因为所有代码都按预期运行。我还将 module_1.py 中的导入更新为:

from .package_2.module_2 import func_2

最后,@jonilyn2730 建议通过将主体放在 main() 函数中,使主体可从其他脚本调用。例如,module_1.py 将是:

from package_1.package_2.module_2 import func_2
def func_1():
    func_2()
def main():
    func_1()
if __name__ == "__main__":
    main()

在这个简单的例子中,它几乎没有什么区别,但它允许在其他脚本中这样做:

from package_1.module_1 import main
main()

因此不再需要直接调用脚本,并且可以在单个脚本中组合多次运行。

【问题讨论】:

    标签: python python-3.x module package


    【解决方案1】:

    没有很好的方法可以在不破坏包其他部分的所有导入的情况下按文件名运行包中的模块。相反,您应该使用 -m 标志从顶级文件夹运行模块:

    python -m package1.module1
    

    当您以这种方式运行模块时,相对或绝对导入都应该可以工作(选择您喜欢的任何一个)。

    请注意,如果您的项目中有循环导入(这样您作为脚本运行的模块也会从其他地方导入),解释器最终会得到该模块的两个副本,一个以 @ 运行987654323@ 和另一个作为其正常名称。这可能会非常尴尬并导致令人困惑的错误。

    如果您经常将模块作为脚本运行,您可能应该创建一个新的顶级脚本模块,从包中导入模块并运行所需的代码(就像您已经在 main.py )。这可以防止充满代码的模块可能存在两次,并且还可以让您受益于从 .pyc 文件加载的缓存字节码(这可能会使您的程序启动速度更快一些)。

    【讨论】:

    • 您的建议有效并正在运行:“python -m package_1.module_1”和“python -m package_1.package_2.module_2”,我可以让两个模块分别运行,但这确实意味着如果我在另一个项目中重用 package_2,我需要更新它的导入语句以反映它不再在 package_1 中的事实。如果不创建对 package_1 的显式依赖,就没有办法让 package_1 使用的 package_2 工作吗?这不是有损于一开始就拥有一个包裹的目的吗?
    • 抱歉,我弄错了——这实际上不是问题。我想在这些情况下,从根目录运行命令是最好的解决方案。
    猜你喜欢
    • 2017-02-25
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 2020-01-30
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    相关资源
    最近更新 更多