2012-04-17 2 views
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(): считывает данные из API потокового трафика Twitter, используя python-requests, следовательно .iter_lines().

Любые идеи? Заранее спасибо.

ответ

1

Цикл for будет делать итератор один раз, и он не будет продолжать проверять self.connections[0] в цикле. Так как @mklauber сказал, используйте что-то вроде threading.Event.

Если предположить, что мы имеем threading.Event экземпляр в качестве self.new_conn и его установки всякий раз, когда есть новое соединение:

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 

Если вам просто нужно цикл, чтобы немедленно прекратить, вы могли бы справиться с этим сделать свой метод .iter_lines() генератор, и сделать генератор проверить:

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

Это красиво инкапсулирует петлю. Ваш исходный код будет работать, как показано на рисунке, и он остановится при появлении нового соединения.

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, если это необходимо.

+0

Это то, что я изначально думал тоже, но мне нужно, чтобы цикл немедленно переключился на новое соединение, он не может дождаться, когда API-интерфейс Twitter будет отправлять новые данные по трубе, чтобы он мог переключаться, он должен немедленно разорваться после соединений [0 ] обновляется. –

+1

Хорошая точка. В этом случае вам, вероятно, понадобится объект мьютекса, который вы можете установить в одном потоке и проверить с другого. Я бы рекомендовал [Event] (http://docs.python.org/library/threading.html#event-objects). – mklauber

Смежные вопросы