2014-01-24 79 views
2

一個PY文件這是test.py:導入內本身

當系統運行
import sys 

a = 50 
b = [1,2] 

def change(): 
    print "Here 1" 
    import test 
    print "Here 2" 
    test.a = -1 
    test.b = [0,1] 
    return 

def main(): 
    print "Here 3" 
    change() 
    print "Here 4" 
    print a, b 

if 1: 
    main() 

上面的Python代碼生成以下的輸出:

Here 3 
Here 1 
Here 3 
Here 1 
Here 2 
Here 4 
-1 [0, 1] 
Here 2 
Here 4 
50 [1, 2] 

我很困惑,爲什麼沒有一個無限循環的「Here 1 \ n Here 3」輸出。打印a,b輸出如何證明是合理的?

+0

謝謝Slater的編輯! –

+0

如果你接受了一個你在這裏找到有用的答案,那麼這將是一件好事,它會導致你的解決方案。如果遇到同樣的問題,它也能幫助讀者快速找到有用的信息。 – idjaw

回答

0

一個文件只能被導入一次。第一次遇到「進口測試」行時成功。當它再次遇到時,解釋器將檢查它是否已經被加載。

程序最初運行時,它不會被視爲「導入」。

14

當您將該文件作爲腳本運行時,它不被認爲是test模塊。它被認爲是__main__模塊。

當執行命中import test時,開始第二次執行文件,其中模塊被認爲是test

當再次執行命令import test時,Python認識到它已經在導入test並且不會重新執行該模塊。相反,它只是將半初始化的test模塊對象加載到當前名稱空間中並繼續。 Python的樂觀假設是你編寫了代碼,以便在導入完成之前不需要test的內容。

當執行到分配到test.atest.b,影響了test模塊,但不__main__,儘管他們來自同一個文件中附帶的事實。因此,來自導入模塊的print a, b反映了新值,而來自__main__print a, b反映了初始值。

+1

恩說。我的第一個想法是「爲什麼他把'__main__'放到這裏,東西只被導入一次並緩存在'sys.modules''中。我的第二個想法是...等一下,他對'__main__'位是正確的(它完美地解釋了總是很好的結果)。從我+1。 – mgilson

+0

+1另外'test'是Py 2.7中的內建模塊 – thefourtheye

0

這個腳本的一般流程如下:

  1. 主運行,所以它打印「這裏3」
  2. 改叫,所以它打印「在這裏1」
  3. 導入時測試,Python運行測試的主要功能
  4. 當第二次調用變化時,python足夠聰明,知道測試已經導入,所以它有效地跳過了那一行。
  5. 導入的主要運行完成
  6. 原始腳本完成運行。
0

雖然user2367112's excellent answer解釋了爲什麼發生這種情況,但這裏沒有任何答案提供解決方法。

有兩種簡單的方法來實現所需的行爲。

  1. 不是導入test,而是使用import __main__代替。如果您使用import __main__ as test分配別名,則甚至不必更改任何其他代碼。
  2. 你可以設置sys.modules['test'] = sys.modules['__main__']告訴python「嘿,這個模塊已經存在」。在此之後,import test將不會重新導入該模塊,從而使您的代碼按預期工作。 sys.modules上的相關文檔可以在here找到。