2013-06-25 35 views
4

我有一個初始化成本高的共享資源,因此我想跨系統訪問它(它基本上用於某些儀器,所以必須是輕量級的)。所以我創建了一個管理設置和訪問的模塊。它會對資源進行惰性初始化並將其存儲在模塊全局變量中。然後我在系統中使用這個模塊的功能來操作資源。
- 現在我想知道是否(或多久)我將不得不重新初始化資源?
- 我知道對象是垃圾收集在CPython上(或更好的是)零引用計數,但存儲在一個模塊計算爲引用,即使此時模塊沒有被執行?Python:模塊全局變量的生命週期

代碼示例:在這裏我們有模塊,其中_connect()很慢。我想在我的系統中使用report_safely(),並最終以儘可能少的方式調用_connect()。

__metrics = None 


def _connect(): 
    global __metrics 

    client = SomeSlowToSetUpClient() 
    __metrics = SomeMetrics(client) 
    client.connect() 


def report_safely(): 
     if not __metrics: 
      _connect() 

     __metrics.execute_lightweight_code() 
+0

要問的一個問題是,你確定在第一次連接之後的任何時候基本上都連接了這個東西**是一個好主意嗎? – voithos

+0

嗯,這個東西只是向服務器發送UDP數據包,所以我沒有看到保持連接的問題? – Zakum

回答

8

不再被引用的對象實際上是垃圾收集的(當它們的引用計數下降到0時它們被自動刪除)。

但是,全局模塊不會將其引用計數降爲0;一旦導入了一個模塊對象(它的名字空間),就會存在於sys.modules映射中。名稱空間本身引用您的對象。

換句話說,您的對象會永遠存在,直到您從模塊名稱空間中刪除它,刪除模塊名稱空間本身(del sys.modules['yourmodule'])或您的python腳本退出。

+0

這聽起來不錯。謝謝Martijn!但是現在我想知道腳本退出的意思。上下文是一個Django應用程序,導入這個東西的模塊在(芹菜)工作線程中執行。這是否意味着模塊在每個工作線程終止時被執行,還是父計數的生命週期?我的意思是......我可以將它導入產卵父線程的某個地方,但聽起來有點笨拙。 – Zakum

+0

@Zakum:Celery工作人員只導入代碼*一次*,然後在線程中運行任務。 –

+0

......這意味着我很好,只要芹菜正在運行。盛大,非常感謝! (爲了以防萬一,這個事情會打開幾個小時/意見,但是看起來你對接受的答案有強烈的要求) – Zakum

0

如果包含全局的模塊在從執行開始到結束的範圍內,那麼全局變量將是。儘管可以使用類實例更清潔。

+0

像Singleton這樣的Java也是我的第一個想法,但是由於我只有@classmethods和類變量在那件事上,所以這看起來相當不錯。另外,Singleton類也會產生與垃圾收集相同的問題。 – Zakum