问题描述
场景
我想要一个多处理器队列,几个工作人员听
如果键盘中断,主进程不应再将新项目放在排队,并在哨兵对象的帮助下,工作人员应优雅地停止。
问题
我使用的当前版本的问题
signal.signal(signal.SIGINT,signal.SIG_IGN)
要忽略Ctrl + C,它也被主进程忽略。
任何想法?
我需要使用多处理工作池吗?一些例子表明我可能必须。我可以继续使用队列吗?
从多进程导入池,进程,队列
import time
进口信号
#http://docs.python.org/3.1/library/multiprocessing.html#multiprocessing.Queue
#http://docs.python.org/3.1/library/multiprocessing.html #multiprocessing.Process
class Worker(Process):
def __init __(self,queue,ident):
super(Worker,self).__ init __()
#忽略信号
signal.signal(signal.SIGINT,signal.SIG_IGN)
self.queue = queue
self.idstr = str(ident)
print Ident+ self.idstr
def run(self):
print'Worker started'
#在这里做一些初始化
print'计算事物$'
为iter(self.queue.get,None)中的数据
print#+ self.idstr +:+ str(data)
time.sleep )
打印#+ self.idstr +队列大小: + str(self.queue.qsize())
打印工作完成
####主要####
request_queue =队列( 10)
在我的范围(4):
工作者(request_queue,i).start()
尝试:
为数据范围(1000000):
request_queue.put(data)
#printQueue Size:+ str(request_queue.qsize())
#Sentinel对象允许清除关闭:每个工作人员1。
在我的范围(4):
request_queue.put(无)
除了KeyboardInterrupt:
打印抓住KeyboardInterrupt,终止工作人员
request_queue.empty()== False:
request_queue.get()
request_queue.put(无)
我想我找到了一个解决方案。仍然我不喜欢我从主人那里得到SIGINT 1次,从工人那里得到4次,但也许我必须和他一起生活。
- 我为中断信号指定了一个信号处理程序。
- 接收到第一个Sig INT后,我忽略更多的SIG Int信号
- 我切换停止标志为TRUE
- 我打破队列插入循环
-
我调用stop函数清除队列并插入停止哨兵
从多进程导入池,进程,队列
导入时间
导入信号
#http: //docs.python.org/3.1/library/multiprocessing.html#multiprocessing.Queue
#http://docs.python.org/3.1/library/multiprocessing.html#multiprocessing.Process
#停止标记循环
stop = False
#定义SIGINT
def signal_handler(sig,frame):
print'您按Ctrl + C! '
global stop
stop = True
#忽略更多Ctrl + C
signal.sig nal(signal.SIGINT,signal.SIG_IGN)
signal.signal(signal.SIGINT,signal_handler)
def stopSentinel(request_queue):
printCTRL Stop队列和插入无
#空现有队列
而request_queue.empty()== False:
request_queue.get()
#一个没有为每个工人
在我的范围(4):
request_queue.put(无)
类工人(进程):
def __init __(self,queue,ident):
super(Worker,self).__ init __()
self.queue = queue
self.idstr = str(ident)
printIdent+ self.idstr
def run(self):
print'Worker started'
#在这里做一些初始化
打印计算事物!
用于iter中的数据(self.queue.get,None):
print#+ self.idstr +:+ str(data)
time .sleep(5)
打印#+ self.idstr +队列大小:+ s tr(self.queue.qsize())
打印工作完成
####主要#####
request_queue =队列(10)
对于范围(4)中的i:
工作者(request_queue,i).start()
### #填充队列与数据####
范围(1000000)中的数据:
request_queue.put(data)
#print队列大小:+ str(request_queue.qsize() )
#Sentinel对象允许清除关闭:每个工作1。
#检查止损
打印检查突破
如果stop == True:
打印停止休息
break
如果stop == True:
stopSentinel(request_queue)
else:
打印正常停止
对于范围(4)中的i:
request_queue。 (无)
From several posts found on stackoverflow i created this code.
Scenario
I want to have a multiprocessing.queue on which several worker "listen"
In case of a keyboard interrupt, the main process should no longer put new items in the queue and with the help of the sentinel objects, the worker should gracefully be stopped.
Problem
My problem with the current version where i use
signal.signal(signal.SIGINT, signal.SIG_IGN)
To ignore the Ctrl + C is that it is also ignored by the main process.
Any Ideas ?Do I need to use the multiprocessing worker pool ? Some examples indicate that i might have to. Can I then still use the queue ?
from multiprocessing import Pool, Process,Queue
import time
import signal
# http://docs.python.org/3.1/library/multiprocessing.html#multiprocessing.Queue
# http://docs.python.org/3.1/library/multiprocessing.html#multiprocessing.Process
class Worker(Process):
def __init__(self, queue,ident):
super(Worker, self).__init__()
# Ignore Signals
signal.signal(signal.SIGINT, signal.SIG_IGN)
self.queue= queue
self.idstr= str(ident)
print "Ident" + self.idstr
def run(self):
print 'Worker started'
# do some initialization here
print 'Computing things!'
for data in iter( self.queue.get, None ):
print "#" + self.idstr + " : " + str(data)
time.sleep(5)
print "#" + self.idstr + "Queue Size: " + str(self.queue.qsize())
print "Worker Done"
#### Main ####
request_queue = Queue(10)
for i in range(4):
Worker( request_queue,i ).start()
try:
for data in range(1000000):
request_queue.put( data )
#print "Queue Size: " + str(request_queue.qsize())
# Sentinel objects to allow clean shutdown: 1 per worker.
for i in range(4):
request_queue.put( None )
except KeyboardInterrupt:
print "Caught KeyboardInterrupt, terminating workers"
while request_queue.empty()==False:
request_queue.get()
request_queue.put( None )
I think I found a solution. Still I don't like that I get the SIGINT 1 time from main and 4 times from the Worker, but maybe I have to live with that.
- I specified a signal handler for the Interrupt Signal.
- After Receiving the first Sig INT I ignore more SIG Int signal
- I switch the stop flag to TRUE
- I break out the queue insert loop
I call stop function which clears the queue and inserts the stop sentinels
from multiprocessing import Pool, Process,Queue import time import signal # http://docs.python.org/3.1/library/multiprocessing.html#multiprocessing.Queue # http://docs.python.org/3.1/library/multiprocessing.html#multiprocessing.Process # Stop Flag for loop stop = False # Define SIGINT def signal_handler(sig, frame): print 'You pressed Ctrl+C!' global stop stop = True # Ignore more Ctrl+C signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGINT, signal_handler) def stopSentinel(request_queue): print "CTRL Stop Queue and insert None" # Empty Existing Queue while request_queue.empty()==False: request_queue.get() # Put One None for each Worker for i in range(4): request_queue.put( None ) class Worker(Process): def __init__(self, queue,ident): super(Worker, self).__init__() self.queue= queue self.idstr= str(ident) print "Ident" + self.idstr def run(self): print 'Worker started' # do some initialization here print 'Computing things!' for data in iter( self.queue.get, None ): print "#" + self.idstr + " : " + str(data) time.sleep(5) print "#" + self.idstr + "Queue Size: " + str(self.queue.qsize()) print "Worker Done" #### Main ##### request_queue = Queue(10) for i in range(4): Worker( request_queue,i ).start() #### Fill Queue with Data #### for data in range(1000000): request_queue.put( data ) #print "Queue Size: " + str(request_queue.qsize()) # Sentinel objects to allow clean shutdown: 1 per worker. # Check for Stop print "Check Breakout" if stop == True: print "Stop Break" break if stop == True: stopSentinel(request_queue) else: print "Normal Stop" for i in range(4): request_queue.put( None )
这篇关于抓住键盘中断以阻止Python多处理工作者在队列中工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!