2017-06-14 91 views
-2

需要一個解決方案或解決方法來從moduleB讀取和寫入moduleA中的變量。下面是代碼:從模塊B讀取和寫入模塊A中的變量

moduleA

import moduleB 

variable = 10 

def changeVariable(): 
    global variable 
    variable = 20 

def main(): 
    print("From moduleA, variable =", variable, " before change.") 
    moduleB.main() 
    print("From moduleA, variable =", variable, " after change.") 

if __name__ == "__main__": 
    main() 

moduleB

import moduleA 

def main(): 
    print("From moduleB, variable =", moduleA.variable, " before change.") 
    moduleA.variable = 20 # Try 1 
    moduleA.changeVariable() # Try 2 
    print("From moduleB, variable =", moduleA.variable, " after change.") 

if __name__ == "__main__": 
    main() 

當運行moduleA我們得到:

  • 從moduleA,改變之前變量= 10。
  • 從moduleB開始,變化前的變量= 10。
  • 從moduleB,變量後變量= 20。
  • 來自moduleA,變化後變量= 10。

下面是使用靜態變量另一個例子:

moduleAA

import moduleBB 

class AA: 
    variable = 0 

    @staticmethod 
    def changeVariable(): 
     AA.variable = 20 

def main(): 
    AA.variable = 10 
    print("From moduleAA, variable =", AA.variable, " before change.") 
    moduleBB.main() 
    print("From moduleAA, variable =", AA.variable, " after change.") 

if __name__ == "__main__": 
    main() 

moduleBB

import moduleAA 

def main(): 
    print("From moduleB, variable =", moduleAA.AA.variable, " before change.") 
    moduleAA.AA.variable = 20 # Try 1 
    moduleAA.AA.changeVariable() # Try 2 
    print("From moduleB, variable =", moduleAA.AA.variable, " after change.") 

if __name__ == "__main__": 
    main() 

當運行moduleAA時,我們得到:

  • 從moduleAA,變量= 10之前改變。
  • 從moduleBB開始,變化前的變量= 0。
  • 從moduleBB,變量後變量= 20。
  • 從moduleAA,變化後的變量= 10。
+3

我已經[解釋](https://stackoverflow.com/questions/44550783/change-global-module-variable-from-another-module)你上次發佈這件事發生了什麼。解決方案是停止依賴循環導入,全局變量,特別是跨模塊全局變量依賴項。所有這些事情都會導致脆弱,難以理解的代碼。 – user2357112

+0

@ user2357112非常感謝您的信息。我不明白如何解決這個問題。所以你在說什麼是不可能修改這個變量?我有一個模塊包含一個異步API和另一個包含GUI的模塊。我需要至少有一個字典在兩者之間共享。這本字典應該是靜態的。 – Yster

+0

如何在模塊之間共享數據的問題已經被問到[很多](https://stackoverflow.com/questions/24875798/python-sharing-variables-between-modules),[many](https:// stackoverflow。 com/questions/14247974/python-how-to-share-a-variable-between-two-modules)[times](https://stackoverflow.com/questions/3338283/python-sharing-global-variables-between-模塊和類-文獻)。 (那些剛剛碰巧是我偶然發現的前三個,還有更多。)你甚至嘗試*搜索「python模塊之間的共享變量」嗎? –

回答

1

當您執行moduleA你運行它作爲一個腳本 - 基本上是一個與__main__名稱模塊,而不是一個「正常」的模塊,這就是它如何被加載。如果你一開始就看sys.modules(在你導入moduleB之前),你不會在那裏找到你的moduleA,但是你會發現模塊__main__(它很快就會擁有variable的值爲10)。

然後當您導入moduleB,它進口moduleA - Python中試圖找到加載moduleA但沒有任何,所以它會嘗試從磁盤,瞧加載它!它會被加載,但這次是moduleA。 Python然後查找從moduleA導入的moduleB,並且由於它已經存在,所以儘管存在循環依賴關係(如果在代碼中有類似的東西 - 你做錯了),它也不會對此產生任何大驚小怪。

無論如何,因爲它現在加載爲moduleA,其if __name__ == "__main__":塊的計算結果爲false,因此不會引起任何額外的大驚小怪。moduleB繼續其執行,但它也不匹配它的if __name__ == "__main__":塊,因此它只是被加載並坐在那裏。

現在我們回到我們的moduleA__main__代表 - 其if __name__ == "__main__":塊計算結果爲真,那麼它所謂的main()功能,進而調用moduleBmain()功能,然後改變variable價值,但在moduleA,不在__main__。所以,現在當它回到__main__並且它試圖讀取它自己的variable值時,它得到10的不變版本。但是,如果您打印出:print(getattr(sys.modules["moduleA"], "variable")),您會看到您的moduleB確實更改了moduleA的變量。

如果你真的想迫使main的變化,儘量讓你的moduleB,如:

import sys 

def main(): 
    moduleA = sys.modules["__main__"] # this is the executing `moduleA` in your case 
    print("From moduleB, variable =", moduleA.variable, " before change.") 
    moduleA.variable = 20 
    print("From moduleB, variable =", moduleA.variable, " after change.") 

if __name__ == "__main__": 
    main() 

這將,從moduleA運行測試的情況下,打印出:

('From moduleA, variable =', 10, ' before change.') 
('From moduleB, variable =', 10, ' before change.') 
('From moduleB, variable =', 20, ' after change.') 
('From moduleA, variable =', 20, ' after change.') 

那是什麼繼續這裏,而你的靜態變量示例也會發生同樣的情況 - 你始終將目標鎖定在你的moduleB的「錯誤」模塊中。無論哪種方式,請不要在任何生產代碼或其他開發人員最終不得不篡改您的代碼的情況下執行此操作 - 循環冗餘是所有事情都很好的禍根。

+0

非常感謝您的解釋和可能的解決方案!我幾乎放棄了對這件事的希望。問題是我不想再次運行moduleA。例如,如果我有一個模塊A的GUI和一個模塊B的異步API。然後它會打開另一個GUI。沒有循環引用可以做到這一點嗎?這個問題的最佳解決方案是什麼?必須很快去睡覺。再次感謝。 – Yster

+1

@Yster - 好的,不要在'moduleB'中加載你的'moduleA',而不是'moduleB'中的'import moduleA',假設你的'moduleA'是'moduleA = sys.modules.get(「__main __」)'仍然是主要的運行腳本。解釋如何避免循環引用,恐怕有點超出了這些評論的範圍 - 它基本上要求重新考慮你想如何設計你的系統,如果沒有辦法(99%的時間存在)圍繞兩個獨立的實體,由於某種原因相互依賴,在它們之間創建一個代理以充當中介。 – zwer