2015-01-13 85 views
3

我在同一目錄下有兩個文件,其中包含我的程序poker.py的內容,另一個包含測試用例poker_test.py。在poker.py結束之後python如何評估模塊執行?

import unittest 
import poker 


class PokerTest(unittest.TestCase): 
     (...) 

,而我發展我有以下commnands:

poker_test.py我執行下面的命令來運行測試用例

if __name__ == "__main__": 
    #imports Test case and unittest 
    from poker_test import * 
    unittest.main() 

一切正常這很好(現在),這個設置非常適合迭代開發。我的問題是,當我運行python時,如何評估poker.py,因爲poker_test.py取決於poker.py,反之亦然?

我有一個大概的想法,但想知道「官方」的答案是什麼。

感謝, -M

+0

注意,單元測試也支持有限的命令行參數:https://docs.python.org/2/library/unittest.html#command- line-interface - 在這種情況下,你可以使用'python -m unittest poker_test.py'而不是'python poker.py'來運行測試,而Bob是你的叔叔。你甚至可以只運行特定的測試。 'python -m unittest poker_test.PokerTest.testSomething' – mgilson

回答

3

根據你是否應該這樣做,正如Alex所說,不惜一切代價避免它。週期性進口是一種罪狀。

隨着那一邊,這很有趣看看發生了什麼事(約 - 它看起來像模塊導入機制是an area that gets tweaked from version to version in Python我給這家主要來源是Python的3.4.2文檔的進口系統)

當內poker_test.py行:

import poker 

被執行時,系統首先檢查模塊已經被加載。加載的模塊位於名爲sys.modules的字典中。

  • 如果導入模塊處於sys.modules已經到pokerpoker_test.py任何引用只是指向一個命名空間。(請注意,在週期性進口的情況下,模塊可能已經被添加到sys.modules,但命名空間的填充可能不完全結束。該模塊的執行可能在那說import this_or_that_other_module行被暫停的那一刻)
  • 如果模塊不存在,則系統會創建一個新的命名空間,將其添加到sys.modules,查找與該poker模塊相關的代碼(在這種情況下,住在poker.py),並開始執行它,把所有的新創建的命名空間中的變量。

所以,你會覺得poker.py被運行一次,並poker_test.py被運行一次,並已經注意到poker是加載模塊,所以進口到此爲止。除...

當一個模塊作爲原始腳本運行時,它將在sys.modules中註冊爲__main__,而不是其實際名稱。

所以poker.py將被稱爲__main__模塊,並作爲一個結果,當poker_test試運行import poker,它無法找到sys.modulespokerpoker被加載兩次,一次爲__main__,並再次爲poker。週期性進口是不受歡迎的,但由於創建兩個相同(ish)名稱空間和可能導致的潛在奇怪錯誤的問題,週期性進口模塊被徹底譴責。

你的代碼還有兩個複雜的問題。

1)from poker_test import *

因爲你正在做的import *,而不是把從poker_test在自己的命名空間創建的所有變量,它被扔進__main__命名空間。

2)if __name__=='__main__':

因爲你只能從poker_test導入模塊是否正在執行主腳本,當poker會從poker_test進口Python解釋器不會觸及該行。所以你的代碼在概念上並不真正循環。 poker作爲__main__進口poker_test其中進口poker並在那裏停止。簡單!

...所以我們不要做循環進口。

一些基準物質:

Official Python 3.4.2 docs on the import system

2008 comp.lang.python discussion on cyclical imports

1

它總是健全以避免循環依賴,就像你在這裏創建了一個。然而,你運氣不好,因爲from poker_test import *出現在poker.py的最後,即在後者定義了它所定義的全部之後,所以它可以通過循環依賴的poker_test.py以良好狀態導入。

但是,雖然這恰好適用於當前的Python版本,但它不受語言規範的保證。爲了牢固,打破循環依賴,例如如下:

  • 把所有的「實質性」的poker.py內容if __name__檢查之前,例如_poker.py
  • poker.py,只是做from _poker import *
  • poker_test.py,而不是的import poker,使用import _poker as poker

這樣,您的依賴關係圖變得非循環,並且作爲結果您的代碼將按照Python的任何正確版本(包括假想的未來版本)的預期工作:-)。