2

これは少し複雑です...

基本的に、私はこの機能を持っています:

def do_loop(self):
    for line in self.connections[0].iter_lines():
            print line

そして、それと並行して常に実行されているスレッドがあり、任意の時点で の値を変更しますconnections[0]

これが発生した場合、connections[0]がスレッドによって外部的に変更された場合、ループは古い を使用し続けます。connections[0]これが起こらないようにする必要がありますconnections[0]。代わりにすぐに新しい を使用する必要があります。

背景として、for line in self.connections[0].iter_lines():は を使用して Twitter ストリーミング API からデータを読み取っていpython-requestsます.iter_lines()

何か案は?前もって感謝します。

4

2 に答える 2

1

簡単な解決策として、次のことをお勧めします。基本的に、接続のコピーを使用し、各ループの後にソースに対してコピーをチェックします。

def do_loop( self ):
    while true:
        conn = copy( connections[0] )
        for line in conn.iter_lines():
            print line
            if conn != connections[0]:
                break

決してエレガントではありませんが、スレッドセーフになるようにコードの多くを徹底的に再設計しなくても、うまくいくはずです。必要に応じて、文を使用しreturnて while ループを終了できます。

于 2012-04-17T20:32:06.840 に答える
1

The for loop is going to make an iterator, once, and it won't keep checking self.connections[0] in the loop. So as @mklauber said, use something like threading.Event.

Assuming that we have a threading.Event instance as self.new_conn and it gets set whenever there is a new connection:

def do_loop(self):
    for line in self.connections[0].iter_lines():
        if self.new_conn.is_set():
            break # or could raise exception here
        print line

If you just need the loop to instantly terminate, you could handle it by making your .iter_lines() method a generator, and making the generator do the check:

def iter_lines(self):
    for line in self.connections[0].private_data_lines:
        if self.new_conn.is_set():
            break
        yield line

This nicely encapsulates the loop. Your original code would work as shown, and it would stop when there was a new connection.

于 2012-04-17T22:07:09.560 に答える