为什么运行子模块(python -m a.c)也会导入包含模块?

时间:2016-06-25 22:02:02

标签: python

假设:

tree

~/dir                                                                          
▶ tree
.
├── a
│   ├── __init__.py
│   ├── c.py
└── b.py

1 directory, 3 files

*.py个文件

~/dir                                                                          
▶ tail -n +1 **/*.py                                                  
==> a/__init__.py <==
print(__name__)
import a.c

==> a/c.py <==
print(__name__)

==> b.py <==
print(__name__)
import a

的I / O

~/dir                                                                          
▶ python3 -m a.c
a
a.c
__main__

模块a.c与模块a无依赖关系。那么,为什么Python运行模块a就好像它正在导入它一样?对我来说这是令人惊讶的行为。我没想到在没有导入的情况下运行脚本会导致脚本本身被导入和评估两次。对于不使用if __name__ == "__main__"

保护的脚本,这不会有危险吗?

这种行为的理由是什么?为什么Python在运行子模块时需要评估包含模块?

2 个答案:

答案 0 :(得分:1)

  

模块a.c与模块a没有依赖关系。那么,为什么Python运行模块a就像导入它一样

current development version

  
    

导入parent.one将隐式执行parent/__init__.pyparent/one/__init__.py。后续导入的parent.twoparent.three将分别执行parent/two/__init__.pyparent/three/__init__.py

  
  

对我而言,这是令人惊讶的行为。我没想到在没有导入的情况下运行脚本会导致脚本本身被导入和评估两次。

不,这并不令人惊讶。想一想:在您的示例中,a包显示的任何对象都由a/__init__.py控制。解释器现在必须评估a/__init__.py以确定是否存在a.c。在此过程中,执行print语句。此外,没有模块导入两次。它只导入一次 - 尽管你可以在技术上多次编写import语句。

答案 1 :(得分:0)

  

模块a.c与模块a

无依赖关系

您将包与模块混淆。

`a` is a package
`c` is a module within package `a`

存在依赖关系:a.c是包a的成员。

有关此问题的常见问题

What's the difference between a Python module and a Python package?

Module vs. Package?

  

那么,为什么Python运行模块a就像导入模块一样?对我来说,这是令人惊讶的行为

导入模块a.c时,python处理包a,包括执行a/__init__.py中的代码,然后执行模块c.py

问:为什么?

答:因为这就是语言所说的。 :)(我知道,那不是为什么你的意思。)

问:为什么?如同,“为什么会这样做,那会有什么好处?”

答:包级别init可能会做一些有用的事情。

包init可以提供东西,成员可以在成员模块启动之前依赖正在执行的包。

您出于某种原因将c放入包a

人们可以简单地将包用于结构组织。如果您有Java经验,您可能会看到这些点就像组织类的方式一样。如果由于这个原因你只使用a,请将__init__.py留空,所有内容都会如您所愿。

但是a/__init__.py包允许其他能力。它确实需要小心使用,但在您需要时可以使用。

  

对于不使用if __name__ == "__main__":

保护的脚本,这不会有危险吗?

是的,你需要清楚地知道什么是要运行的脚本(例如python b.py)以及什么是模块作为类和函数的容器。

通常,模块并不意味着作为独立脚本执行。常见的例外是测试和开发期间。然后你会经常看到一些测试代码

if __name__ == "__main__":
    x = somefunction()
    print(x)
    a = SomeClass()
    y = a.foo()
    print(y)