2011-01-20 24 views
-1

sharevar.pyのようなグローバルファイルをインポートする、いくつかのワーカークラスを作成するPythonスレッディングコードを書くときに問題が発生しました.regdevidのような変数が必要です。 レジスタデバイスをトラッキングしていますidを変更すると、あるスレッドがその値を変更すると、他のスレッドは が新鮮になりますが、その結果は次のようになります:1つのスレッドが値を変更すると、他のスレッドは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

あり*あなた*に何か問題はおそらくありませんが、多分あなたはあなたのコードを表示する必要があります:あなたはグローバル変数を再バインドしたい場合はglobal文を使用します。 –

+0

コードを正しくフォーマットしてください... – fossilet

答えて

3

実際のコードを掲載してもよろしいですか?次の2つの異なるモジュールからRegDevIDをインポート:

# thread b 
from ShareVar import send_queue, RegDevID 

# thread a 
from UserShare import RegDevID 

いずれかの方法を、あなたのproblamはスレッドとは何の関係もありません。代入文として 'somemodule import somevar'を考えてください。あなたが現在のモジュールに新鮮な名前を作成している他のモジュールからRegDevIDをインポートすると

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

:それはまだ続いロードされていない場合は、モジュールをロードするためのいくつかの魔法とほぼ同じ。オブジェクトを変更すると、オブジェクトの他のユーザーに変更が表示されますが、このモジュールで名前を再バインドすると、ローカル名にのみ影響します。元のモジュールでは何も変更されません。

は、代わりに、別のモジュールで変数を再バインドする必要があります。

コースの場合を除き
import ShareVar 
... 
ShareVar.RegDevID = data 

あなたがあなたの共有状態を管理するためのクラスを作成する場合は、上の非常に良く見つけることができます。コードの

あなたの第2ビットは、ローカルおよびグローバル変数を誤解ejustさ:関数内

def SetVar(self): 
    RegDevID = 999 

は、同じ名前のグローバル変数とは何の関係もありません新しいローカル変数RegDevIDを作成しました。

def SetVar(self): 
    global RegDevID 
    RegDevID = 999 
+0

申し訳ありませんが、私の間違いです、はい、彼らは同じファイルです... – liunx

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

+0

それは動作しません、私はサンプルをより簡単にするでしょう... – liunx

+0

どうも私はこの問題を解決することができます、私は自分のコードをきれいにしたいので、ファイルごとに1つのスレッドクラスが、本当にする必要がありますいくつかの変数を共有し、これらの変数は書き込み可能でなければならないので、それを実現する方法はありますか? – liunx

関連する問題