2017-01-02 4 views
0

コールバックメソッド(イベントハンドラ)で作成されたグローバル状態変数を作成しようとしています。 しかし、コールバックは別のメモリ位置にコピー(深い)を作成しますが、他の方法では(もちろん)見られません。ここで 状況python:別のスレッドからグローバル変数に書き込むと、コピーが作成されます

class Server: 
    def __init__(self): 
    self.callbacks=[] 
    #create a web server instance to listen to requests 
    self.app=Flask("test") 

    def add_callback(self, func): 
    self.calbacks.append(func) 
    self.app.add_url_rule("/test", "test", self.handle_http_request) 

    def handle_http_request(self): 
    content = request.get_json(silent=True) 
    for ca in self.callbacks: 
     ca(content) 

    def start_server(self): 
    #some stuff starting flask here... 


class SomeModule: 
    def __init__(self): 
    self.ws=Server() 
    self.ws.add_callback(self.callback) 
    self.callback_called=False 

    def callback(self, content): 
    print "callback executing---" 
    print "var addr before callback assign: "+str(hex(id(self.callback_called))) 
    self.callback_called=True 
    print "var addr after callback assign: "+str(hex(id(self.callback_called))) 

    def start(self): 
    self.ws.start() 
    #send a request to the server using the request library, which invokes all the trigger 
    #check the state variable: 
    print "var addr before check: "+str(hex(id(self.callback_called))) 
    if (not self.callback_called): 
     raise Exception("error...") 

if __name__ == '__main__': 
    sm=SomeModule() 
    sm.start() 

は出力がされている。

 
callback executing--- 
var addr before callback assign: 0x927910 
var addr before callback assign: 0x927930 
var addr before check: 0x927910 

誰も私にこれを回避するためにどのような方法を提案することはできますか? C++ではポインタとmutexにアクセスする方法を明確にしています。ここでは、私は変数の安全な書き込みを行うための方法を見つけるために管理していない...

ありがとうたくさんの事前に!

答えて

1

マルチスレッドを使用していて、タグでマルチプロセッシングを使用していないので、私はまだこの回答を投稿しています。いくつか参考になるかもしれません。

あなたが言ったようにコピーされたオブジェクトはimmutableです。 dictionariesのような他の変数は、機能や脅威から操作できない傾向があります(スレッドが特定のケースにのみ適用されるかどうかはわかりません)。

たとえば、dictをパラメータとしてスレッドに渡すと、その変数は操作でき、それは変数の元のバージョンに影響します。

ただし、これは危険です。更新の衝突、アクセス違反などがあり、一般的には状況がどこで発生したかを把握するのが難しい場合があります。

ただし、dictをスレッドに渡して変更を提示する方法の例を次に示します。原油ですが、実用的な例が得られます。

from threading import * 

class server(Thread): 
    def __init__(self, o): 
     self.o = o 
     Thread.__init__(self) 
     self.start() 

    def run(self): 
     for i in range(3): 
      self.o['test'] = i 

test_var = {'test' : 0} 
server(test_var) 

while len(enumerate()) > 1: # Stupid and oversimplified wait for threads to end. 
    pass 

print(test_var) 
+0

私は変数を交換します。ありがとうございましたself.callback_calledはdictでメモリ検査は実際に同じ位置を示しますが、varibaleがeg.''self.callback_called ['done'] = True'''に設定されていても、私は何かが分かっていないような感じ.... :( – mojovski

+0

@mojovskiあなたはprinですか?変数をすばやく調整しますか?私のテストでは完璧に動作するからです。 https://gist.github.com/で試用コードを貼り付けることができますか? – Torxed

0

問題は実際にはどこか他の場所です。 :(理由はFlask(Webサーバー)が別のスレッドで起動されていて、何らかの理由でインスタンスがコピーされてしまったからです。それ以上は掘り下げずにFlaskを使うのを避けてcherrypyに切り替え、モードを-blocking。 Thinkgsは予想通りそこに動作するように始めた。

は@torxed、あなたの助けのためにどうもありがとうございました。それは確かに正しい方向に私を指摘!

+0

あなたは歓迎以上のことです:)悪いことに、質問はFlaskでタグ付けされていませんでした。私はあなたのコードでそれを見落としたからです。 – Torxed

関連する問題