Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 4, 2011 11:16:27

plusplus
От:
Зарегистрирован: 2009-01-05
Сообщения: 418
Репутация: +  15  -
Профиль   Отправить e-mail  

queue.join и KeyboardInterrupt

Есть способы в многопоточном скрипте, в котором пул потоков организован с помощью очереди Queue и заблокирован методом join перехватывать исключение KeyboardInterrupt. Нашел один способ http://www.regexprn.com/2010/05/killing-multithreaded-python-programs.html, но хочется всё-таки использовать очереди.



Офлайн

#2 Ноя. 4, 2011 12:39:19

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

queue.join и KeyboardInterrupt

Нет.



Офлайн

#3 Ноя. 7, 2011 09:23:54

Enchantner
От:
Зарегистрирован: 2009-02-11
Сообщения: 442
Репутация: +  0  -
Профиль   Отправить e-mail  

queue.join и KeyboardInterrupt

plusplus
Можно передать потокам указатель ещё на одну очередь, “сервисную”, и кидать в неё команды на выход. Каждый поток будет в бесконечном цикле пробовать неблокирующе читать из неё и при получении убивать себя. По KeyboardInterrupt надо будет только лишь кинуть это сообщение об убийстве в сервисную очередь.



Офлайн

#4 Янв. 15, 2012 06:39:18

plusplus
От:
Зарегистрирован: 2009-01-05
Сообщения: 418
Репутация: +  15  -
Профиль   Отправить e-mail  

queue.join и KeyboardInterrupt

Сделал таким образом, тут никаких подводных камней нет? Подскажите.

    # -*- coding: utf-8 -*-  
import threading, Queue, time
import traceback

class Worker(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.__queue = queue

self.kill_received = False # флаг прекращения работы
def run(self):
while not self.kill_received:

try: item = self.__queue.get_nowait() # ждём данные
except Queue.Empty: break

try: self.work(item)
except Exception: traceback.print_exc()

time.sleep(0.5)
self.__queue.task_done() # задача завершена
self.__queue.put(item) # зациклим
return
def work(self,item):
print item

def main():
queue = Queue.Queue()
num_threads = 5 # 5 потоков

threads = []
for x in xrange(100):
queue.put(x) # заносим данные в очередь
for i in xrange(num_threads):
t = Worker(queue) # создаем нить
threads.append(t)
t.start() # стартуем
time.sleep(0.1)

#Пока в "живых" не останется только главный поток, ждем.
while threading.activeCount()>1:
try:
time.sleep(1)
except KeyboardInterrupt:
print "Ctrl-c received! Sending kill to threads..."
for t in threads:
t.kill_received = True # даем сигнал о завершении всем потокам
print "Done!"
if __name__ == '__main__':
main()



Офлайн

#5 Янв. 15, 2012 19:45:57

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

queue.join и KeyboardInterrupt

а зачем вам

while threading.activeCount()>1: 
...
???
Равно как и task_done не имеет смысла без join



Офлайн

#6 Янв. 15, 2012 20:01:52

plusplus
От:
Зарегистрирован: 2009-01-05
Сообщения: 418
Репутация: +  15  -
Профиль   Отправить e-mail  

queue.join и KeyboardInterrupt

Андрей Светлов
а зачем вам
while threading.activeCount()>1:

???
Равно как и task_done не имеет смысла без join
Ну task_done да, просто старый скрипт с очередями переделал, можно очереди вообще убрать. А насчет threading.activeCount(), а как тогда я без него из цикла выйду? Мне же нужно дождаться пока все потоки закончат свою работу и только потом продолжать основной тред.



Офлайн

#7 Янв. 15, 2012 20:07:01

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

queue.join и KeyboardInterrupt

Можно завести флаг «работает» в каждом потоке. По окончании run его ставить.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version