python如何评估模块执行?
我在同一个目录中有两个文件,一个包含我的程序python如何评估模块执行?,python,unit-testing,Python,Unit Testing,我在同一个目录中有两个文件,一个包含我的程序poker.py的内容,另一个包含测试用例poker\u test.py 在poker_test.py中,我执行以下命令来运行测试用例: import unittest import poker class PokerTest(unittest.TestCase): (...) 在我开发poker.py时,在poker.py的末尾,我有以下几点建议: if __name__ == "__main__": #imports Te
poker.py
的内容,另一个包含测试用例poker\u test.py
在poker_test.py
中,我执行以下命令来运行测试用例:
import unittest
import poker
class PokerTest(unittest.TestCase):
(...)
在我开发poker.py时,在poker.py的末尾,我有以下几点建议:
if __name__ == "__main__":
#imports Test case and unittest
from poker_test import *
unittest.main()
一切都很好(目前),这种设置对于迭代开发非常有用。我的问题是,如果poker\u test.py
依赖于poker.py
,反之亦然,那么当我运行它时,python如何评估poker.py
我有一个粗略的想法,但不知道“官方”的答案是什么
谢谢,
-M避免像您在这里创建的循环依赖关系总是最合理的。然而,幸运的是,来自poker_测试导入的位于poker.py
的末尾,也就是说,在后者定义了它所定义的所有内容之后,因此它可以通过循环相关的poker_测试.py
以良好的状态导入
然而,虽然这在当前Python版本中正常工作,但语言规范并不能保证这一点。为保证稳定性,请打破循环依赖关系,例如:
- 将
if\uuuu name\uuuu
检查前的poker.py
的所有“实质性”内容移动到例如\u poker.py
- 在
poker.py
中,只需从\u poker import*
在poker\u test.py
中,使用import\u poker作为扑克,而不是import poker
这样,依赖关系图就变成了非循环的,因此您的代码在任何正确的Python版本中都能按预期工作,包括假设的未来版本:-)。关于您是否应该这样做,正如Alex所说,不惜一切代价避免这样做。周期性进口是一种罪恶的状态
撇开这一点不谈,看看发生了什么很有意思(大致上,模块导入机制是这样的。我的主要来源是导入系统上的Python 3.4.2文档)
当poker\u test.py中的行
import poker
执行时,系统首先检查模块是否已加载。加载的模块存在于一个名为sys.modules
的字典中
- 如果要导入的模块已经在
sys.modules
中,则poker\u test.py
中对poker
的任何引用都只指向该名称空间。(请注意,在周期性导入的情况下,模块可能已经添加到sys.modules
,但命名空间的填充可能尚未完全结束。该模块的执行可能会在显示导入此\u或\u其他\u模块
的行暂停。)
- 如果模块不在那里,则系统创建一个新名称空间,将其添加到
sys.modules
,查找与poker
模块相关联的代码(在本例中,位于poker.py
)并开始执行,将所有变量放入新创建的名称空间中
因此,您可能认为poker.py
运行一次,而poker\u test.py
运行一次,并且已经注意到poker
是一个已加载的模块,因此导入到此结束。除了
当模块作为原始脚本运行时,它将在sys.modules
中注册为\uuuu main\uuuu
,而不是其实际名称
因此,poker.py
将被称为\uuuuu main\uuuuu
模块,因此,当poker\u测试
尝试运行import poker
时,它无法在sys.modules
下找到poker
<代码>扑克
将加载两次,一次作为\uuuu main\uuuu
加载,另一次作为扑克
加载。周期性导入是不受欢迎的,但是\uuuu main\uuu
模块的周期性导入是完全不受欢迎的,因为创建两个相同(ish)名称空间的问题以及可能导致的潜在奇怪错误
代码中还有两个复杂之处
1) 来自扑克测试导入的*
因为您正在执行一个import*
,而不是将从poker\u test
创建的所有变量放在它自己的名称空间中,它会被抛出到\uuuu main\uuu
名称空间中
2) 如果名称=主名称:
由于您仅从poker\u test
导入,如果模块是正在执行的主脚本,那么当poker
从poker\u test
导入时,Python解释器将不会触及该行。因此,您的代码在概念上并不是真正的循环<代码>扑克
作为\uuuuu main\uuuuuuu
导入poker\u测试
,导入扑克
并在那里停止。简单
…所以我们不要做循环导入
一些参考资料:
请注意,unittest还支持有限的命令行参数:--在本例中,您要运行测试,而不是
python poker.py
,您需要执行python-m unittest poker\u test.py
,Bob是您的叔叔。您甚至只能运行特定的测试python-m unittest poker\u test.PokerTest.testSomething