2011-01-20 167 views
-1

我在編寫python線程代碼時遇到了一個問題,那就是我寫了一些線程類的工作人員,他們都導入了像sharevar.py這樣的全局文件,我需要一個像regdevid一樣的變量來保持 跟蹤註冊設備id,那麼當一個線程改變它的值時,其他線程可以得到它新鮮的結果是:當一個線程改變它的值時,其他線程仍然獲得我在sharevar.py文件中定義的默認值,爲什麼? 有什麼不對嗎?Python全局變量線程

# thread a 
from UserShare import RegDevID 
import threading 
class AddPosClass(threading.Thread): 
global commands 
# We need a pubic sock, list to store the request 
def __init__(self, queue): 
    threading.Thread.__init__(self) 
    self.queue = queue 

def run(self): 
    while True: 
     data = self.queue.get() 
     #print data 
     RegDevID = data 
     #print data 
     send_queue.put(data) 
     self.queue.task_done() 
# thread b 
import threading 
from ShareVar import send_queue, RegDevID 
""" 
AddPos -- add pos info on the tail of the reply 
""" 
class GetPosClass(threading.Thread): 
    global commands 
    # We need a pubic sock, list to store the request 
    def __init__(self, queue): 
     threading.Thread.__init__(self) 
     self.queue = queue 

    def run(self): 
     while True: 
      data = self.queue.get() 
      #print data 
      data = RegDevID 
      #print data 
      send_queue.put(data) 
      self.queue.task_done() 
# ShareVar.py 
RegDevID = '100' 

就是這樣,當線程a改變RegDevID時,線程b仍然得到它的默認值。 感謝先進。

from ShareVar import RegDevID 

class Test(): 
    def __init__(self): 
     pass 
    def SetVar(self): 
     RegDevID = 999 
    def GetVar(self): 
     print RegDevID 

if __name__ == '__main__': 
    test = Test(); 
    test.SetVar() 
    test.GetVar() 

的ShareVar.py:

RegDevID = 100 

結果:

100 

爲什麼呢?

+5

有可能沒有什麼不妥*你*,但也許你應該表現出你的代碼。 – 2011-01-20 07:21:35

+0

請正確格式化您的代碼... – fossilet 2013-02-18 09:40:57

回答

3

您確定發佈了您的實際代碼嗎?你進口RegDevID從兩個不同的模塊:

# thread a 
from UserShare import RegDevID 

VS

# thread b 
from ShareVar import send_queue, RegDevID 

無論哪種方式,您problam無關螺紋加工。把'somemodule import somevar'看作是一個賦值語句。

somevar = sys.modules['somemodule'].somevar 

當您從您所創建的電流模塊中的新名稱的其他模塊導入RegDevID:大致相當於一些魔術如果它尚未加載,然後加載模塊。如果你改變對象,那麼對象的其他用戶將看到更改,但是如果你重新綁定這個模塊中的名字,那麼隻影響本地名稱,它不會改變原始模塊中的任何東西。

相反,你需要重新綁定變量的另一個模塊:

import ShareVar 
... 
ShareVar.RegDevID = data 

當然除了你會發現你會得到更好的,如果你創建一個類來管理您的共享狀態。

你的代碼第二位ejust誤解局部和全局變量:

def SetVar(self): 
    RegDevID = 999 

在函數內部創建了一個新的局部變量RegDevID這是無關的相同名稱的全局變量。如果你想重新綁定一個全局變量使用global聲明:

def SetVar(self): 
    global RegDevID 
    RegDevID = 999 
6

我的猜測是你試圖訪問共享變量沒有lock。如果您沒有獲取鎖並嘗試在一個線程中讀取共享變量,而另一個線程正在寫入該值,則該值可能不確定。

要解決此問題,請確保在讀取或寫入之前獲取線程中的鎖定。

import threading 

# shared lock: define outside threading class 
lock = threading.RLock() 
# inside threading classes... 
# write with lock 
with lock: #(python 2.5+) 
    shared_var += 1 
# or read with lock 
with lock: 
    print shared_var 

閱讀關於Python threading

回答您的底部問題作用域:

在你的底樣,你遇到了作用域的問題。在SetVar()中,您將爲函數創建一個本地標籤RegDevID。在GetVar()中,您試圖從標籤RegDevID中讀取,但未定義。所以,它看起來更高,並且在導入中找到一個定義。如果希望讓變量引用相同的數據,則變量需要處於相同的範圍內。

儘管範圍是靜態確定的,但它們是動態使用的。 在執行期間的任何時候,有 至少三個嵌套的範圍,其 命名空間是可以直接訪問:

最裏面的範圍,這是首先搜索,包含本地名稱 所述的任何封閉功能範圍,其中被搜索開始 與最近的封閉範圍, 包含非本地的,也 非全局名稱 下一個到最後一個範圍包含當前模塊的全局名稱 最外層的範圍(最後搜索)是包含 內置的命名空間在名稱

如果名稱聲明爲全局名稱,則所有 引用和賦值均直接轉到 到包含 模塊全局名稱的中間作用域。否則, 最裏面的範圍之外發現的所有 變量是隻讀的(一個 嘗試寫這樣的變量 只會在最裏面的範圍內創建一個新的本地 變量, 離開同名外 變量不變) 。

Read about scoping

+0

謝謝,我會試試看。 – liunx 2011-01-20 07:59:41