我在同一目录中有两个文件,一个包含我的程序poker.py
的内容,另一个包含测试用例poker_test.py
。
在poker_test.py
中,我执行以下命令来运行测试用例:
import unittest
import poker
class PokerTest(unittest.TestCase):
(...)
然后在poker.py
结束时我正在开发我有以下的commnands:
if __name__ == "__main__":
#imports Test case and unittest
from poker_test import *
unittest.main()
一切正常(现在),这种设置非常适合迭代开发。我的问题是python在运行时如何评估poker.py
,因为poker_test.py
取决于poker.py
,反之亦然?
我有一个粗略的想法,但想知道"官方"答案是。
谢谢, -M
答案 0 :(得分:4)
就是否应该这样做,正如亚历克斯所说,不惜一切代价避免它。周期性进口是一种罪恶状态。
除此之外,看一下发生的事情很有意思(粗略地说 - 看起来模块导入机制是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
中对poker_test.py
的任何引用都只指向该命名空间。 (请注意,在循环导入的情况下,模块可能已经添加到sys.modules
,但是命名空间的填充可能还没有完全结束。该模块的执行暂时可能会暂停import this_or_that_other_module
)sys.modules
,查找与poker
模块关联的代码(在这种情况下,生活在{ {1}})并开始执行它,将所有变量放在新创建的命名空间中。因此,您认为poker.py
运行一次,poker.py
运行一次并且已经注意到poker_test.py
是一个已加载的模块,因此导入结束。除了...
当模块作为原始脚本运行时,它会在poker
中注册为__main__
,而不是其实际名称。
所以sys.modules
将被称为poker.py
模块,因此,当__main__
尝试运行poker_test
时,它无法找到import poker
1 {}在poker
下。 sys.modules
将加载两次,一次加载为poker
,另一次加载为__main__
。周期性的导入是不受欢迎的,但poker
模块的周期性导入是彻头彻尾的谴责,因为这个问题创建了两个相同的(ish)命名空间以及可能产生的奇怪错误。
您的代码中还有两个复杂问题。
1)__main__
因为您正在执行from poker_test import *
,而不是将import *
中创建的所有变量放在其自己的命名空间中,而是将其抛入poker_test
命名空间。
2)__main__
因为如果模块是正在执行的主脚本,您只从if __name__=='__main__':
导入,那么从poker_test
导入poker
时,Python解释器将不会触及该行。所以你的代码在概念上并没有真正循环。 poker_test
为poker
导入__main__
导入poker_test
并停在那里。简单!
...所以我们不要进行循环导入。
一些参考资料:
答案 1 :(得分:2)
总是最难避免像你在这里创建的循环依赖。但是你运气好,因为from poker_test import *
出现在poker.py
的最后,即在后者定义了它所定义的所有内容之后,所以它可以通过循环依赖{导入一个良好的状态} {1}}。
然而,虽然这恰好适用于当前的Python版本,但语言规范并不能保证这一点。为了坚固,打破循环依赖,例如:
poker_test.py
检查之前poker.py
的内容,例如if __name__
_poker.py
中,只需执行poker.py
from _poker import *
中,而不是poker_test.py
,请使用import poker
这样,您的依赖图变为非循环,因此您的代码将在任何正确版本的Python中按预期工作,包括假设的未来: - )。