Найти - Пользователи
Полная версия: queue.join и KeyboardInterrupt
Начало » Python для экспертов » queue.join и KeyboardInterrupt
1
plusplus
Есть способы в многопоточном скрипте, в котором пул потоков организован с помощью очереди Queue и заблокирован методом join перехватывать исключение KeyboardInterrupt. Нашел один способ http://www.regexprn.com/2010/05/killing-multithreaded-python-programs.html, но хочется всё-таки использовать очереди.
Андрей Светлов
Нет.
Enchantner
plusplus
Можно передать потокам указатель ещё на одну очередь, “сервисную”, и кидать в неё команды на выход. Каждый поток будет в бесконечном цикле пробовать неблокирующе читать из неё и при получении убивать себя. По KeyboardInterrupt надо будет только лишь кинуть это сообщение об убийстве в сервисную очередь.
plusplus
Сделал таким образом, тут никаких подводных камней нет? Подскажите.
    # -*- 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()
Андрей Светлов
а зачем вам
while threading.activeCount()>1: 
...
???
Равно как и task_done не имеет смысла без join
plusplus
Андрей Светлов
а зачем вам
while threading.activeCount()>1:

???
Равно как и task_done не имеет смысла без join
Ну task_done да, просто старый скрипт с очередями переделал, можно очереди вообще убрать. А насчет threading.activeCount(), а как тогда я без него из цикла выйду? Мне же нужно дождаться пока все потоки закончат свою работу и только потом продолжать основной тред.
Андрей Светлов
Можно завести флаг «работает» в каждом потоке. По окончании run его ставить.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB