python 如何评估模块执行?
How does python evaluate Module execution?
我在同一目录中有两个文件,一个包含我的程序内容 poker.py
,另一个包含测试用例 poker_test.py
。
在 poker_test.py
中,我对 运行 测试用例执行以下命令:
import unittest
import poker
class PokerTest(unittest.TestCase):
(...)
然后在 poker.py
结束时我正在开发我有以下命令:
if __name__ == "__main__":
#imports Test case and unittest
from poker_test import *
unittest.main()
一切正常(目前)并且此设置非常适合迭代开发。我的问题是,当我 运行 时 python 如何评估 poker.py
,因为 poker_test.py
取决于 poker.py
,反之亦然?
我有一个大概的想法,但想知道 "official" 答案是什么。
谢谢,
-M
避免像您在此处创建的那样的循环依赖关系总是最合理的。然而你很幸运,因为 from poker_test import *
出现在 poker.py
的最后,也就是说,在后者定义了它定义的所有内容之后,它可以被循环依赖 poker_test.py
.
然而,虽然这恰好适用于当前 Python 版本,但语言规范不能保证。为了solidity,打破循环依赖,例如如下:
- 在
if __name__
检查之前移动 poker.py
的所有 "substantial" 内容,例如 _poker.py
- 在
poker.py
中,只做from _poker import *
- 在
poker_test.py
中,而不是 import poker
,使用 import _poker as poker
这样,您的依赖关系图就变成了非循环的,因此您的代码将在 Python 的任何正确版本中按预期工作,包括假设的未来版本:-)。
至于你是否应该这样做,正如亚历克斯所说,不惜一切代价避免它。周期性进口是一种罪恶状态。
除此之外,看看发生了什么很有趣(大致 - 模块导入机制看起来是 an area that gets tweaked from version to version in Python。我的主要来源是 Python 3.4.2 文档导入系统)
当poker_test.py
内的行:
import poker
执行后,系统首先检查模块是否已经加载。加载的模块位于名为 sys.modules
.
的字典中
- 如果正在导入的模块已经在
sys.modules
中,则 poker_test.py
中对 poker
的任何引用都指向该命名空间。 (请注意,在循环导入的情况下,模块可能已经添加到 sys.modules
,但命名空间的填充可能尚未完全结束。该模块的执行可能会在下面的行暂停import this_or_that_other_module
)
- 如果模块不存在,则系统创建一个新的命名空间,将其添加到
sys.modules
,查找与 poker
模块关联的代码(在本例中,living in poker.py
) 并开始执行它,将所有变量放入新创建的命名空间中。
所以你会认为 poker.py
获得了 运行 一次,而 poker_test.py
获得了 运行 一次并且已经注意到 poker
是一个加载的模块,所以导入到此结束。除了...
当一个模块是 运行 作为原始脚本时,它在 sys.modules
中被注册为 __main__
,而不是它的实际名称。
所以poker.py
将被称为__main__
模块,结果,当poker_test
尝试运行宁import poker
时,它可以在 sys.modules
下找不到 poker
。 poker
将 加载两次,一次作为 __main__
,另一次作为 poker
。循环导入是不受欢迎的,但是 __main__
模块的循环导入是完全谴责的,因为创建两个相同的(ish)命名空间的问题以及可能导致的潜在奇怪错误。
您的代码中还有两个问题。
1) from poker_test import *
因为你正在做一个 import *
,而不是将所有从 poker_test
创建的变量放在它自己的命名空间中,它被扔进 __main__
命名空间。
2) if __name__=='__main__':
因为如果模块是正在执行的主脚本,您只是从 poker_test
导入,所以当 poker
从 poker_test
。所以你的代码在概念上并不是真正的循环。 poker
as __main__
imports poker_test
which imports poker
and stop there。简单!
...所以我们不要进行循环导入。
一些参考 material:
我在同一目录中有两个文件,一个包含我的程序内容 poker.py
,另一个包含测试用例 poker_test.py
。
在 poker_test.py
中,我对 运行 测试用例执行以下命令:
import unittest
import poker
class PokerTest(unittest.TestCase):
(...)
然后在 poker.py
结束时我正在开发我有以下命令:
if __name__ == "__main__":
#imports Test case and unittest
from poker_test import *
unittest.main()
一切正常(目前)并且此设置非常适合迭代开发。我的问题是,当我 运行 时 python 如何评估 poker.py
,因为 poker_test.py
取决于 poker.py
,反之亦然?
我有一个大概的想法,但想知道 "official" 答案是什么。
谢谢, -M
避免像您在此处创建的那样的循环依赖关系总是最合理的。然而你很幸运,因为 from poker_test import *
出现在 poker.py
的最后,也就是说,在后者定义了它定义的所有内容之后,它可以被循环依赖 poker_test.py
.
然而,虽然这恰好适用于当前 Python 版本,但语言规范不能保证。为了solidity,打破循环依赖,例如如下:
- 在
if __name__
检查之前移动poker.py
的所有 "substantial" 内容,例如_poker.py
- 在
poker.py
中,只做from _poker import *
- 在
poker_test.py
中,而不是import poker
,使用import _poker as poker
这样,您的依赖关系图就变成了非循环的,因此您的代码将在 Python 的任何正确版本中按预期工作,包括假设的未来版本:-)。
至于你是否应该这样做,正如亚历克斯所说,不惜一切代价避免它。周期性进口是一种罪恶状态。
除此之外,看看发生了什么很有趣(大致 - 模块导入机制看起来是 an area that gets tweaked from version to version in Python。我的主要来源是 Python 3.4.2 文档导入系统)
当poker_test.py
内的行:
import poker
执行后,系统首先检查模块是否已经加载。加载的模块位于名为 sys.modules
.
- 如果正在导入的模块已经在
sys.modules
中,则poker_test.py
中对poker
的任何引用都指向该命名空间。 (请注意,在循环导入的情况下,模块可能已经添加到sys.modules
,但命名空间的填充可能尚未完全结束。该模块的执行可能会在下面的行暂停import this_or_that_other_module
) - 如果模块不存在,则系统创建一个新的命名空间,将其添加到
sys.modules
,查找与poker
模块关联的代码(在本例中,living inpoker.py
) 并开始执行它,将所有变量放入新创建的命名空间中。
所以你会认为 poker.py
获得了 运行 一次,而 poker_test.py
获得了 运行 一次并且已经注意到 poker
是一个加载的模块,所以导入到此结束。除了...
当一个模块是 运行 作为原始脚本时,它在 sys.modules
中被注册为 __main__
,而不是它的实际名称。
所以poker.py
将被称为__main__
模块,结果,当poker_test
尝试运行宁import poker
时,它可以在 sys.modules
下找不到 poker
。 poker
将 加载两次,一次作为 __main__
,另一次作为 poker
。循环导入是不受欢迎的,但是 __main__
模块的循环导入是完全谴责的,因为创建两个相同的(ish)命名空间的问题以及可能导致的潜在奇怪错误。
您的代码中还有两个问题。
1) from poker_test import *
因为你正在做一个 import *
,而不是将所有从 poker_test
创建的变量放在它自己的命名空间中,它被扔进 __main__
命名空间。
2) if __name__=='__main__':
因为如果模块是正在执行的主脚本,您只是从 poker_test
导入,所以当 poker
从 poker_test
。所以你的代码在概念上并不是真正的循环。 poker
as __main__
imports poker_test
which imports poker
and stop there。简单!
...所以我们不要进行循环导入。
一些参考 material: