我需要在主过程中对子进程中发生的随机事件做出反应。我用main和子进程之间的队列实现了这个,并且在主进程的辅助线程中运行了一个'queue poller',每次在队列中找到一个项目时都调用一个回调函数。代码在下面,似乎工作。 问题1:您能否告诉我策略是否正确或是否存在更简单的问题? 问题2:我试图在停止主循环时终止子进程和辅助线程,但它失败了,至少在spyder中失败了。我该怎么做才能正确终止一切? 谢谢你的帮助: - )
from threading import Thread
from multiprocessing import Process, Queue
from time import sleep
from random import random
class MyChildProcess(Process):
"""
This process runs as a child process of the main process.
It fills a queue (instantiated in the main process - main thread) at random times.
"""
def __init__(self,queue):
super(MyChildProcess,self).__init__()
self._q = queue # memorizes the queue
self._i = 0 # attribute to be incremented and put in the queue
def run(self):
while True:
self._q.put(self._i) # puts in the queue
self._i += 1 # increment for next time
sleep(random()) # wait between 0 and 1s
class myListenerInSeparateThreadOfMainProcess():
"""
This listener runs in a secondary thread of the main process.
It polls a queue and calls back a function for each item found.
"""
def __init__(self, queue, callbackFunction):
self._q = queue # memorizes the queue
self._cbf = callbackFunction # memorizes the queue
self.pollQueue()
def pollQueue(self):
while True:
sleep(0.2) # polls 5 times a second max
self.readQueue()
def readQueue(self):
while not self._q.empty(): # empties the queue each time
self._cbf(self._q.get()) # calls the callback function for each item
def runListener(q,cbf):
"""Target function for the secondary thread"""
myListenerInSeparateThreadOfMainProcess(q,cbf)
def callBackFunc(*args):
"""This is my reacting function"""
print 'Main process gets data from queue: ', args
if __name__ == '__main__':
q= Queue()
t = Thread(target=runListener, args=(q,callBackFunc))
t.daemon=True # try to have the secondary thread terminated if main thread terminates
t.start()
p = MyChildProcess(q)
p.daemon = True # try to have the child process terminated if parent process terminates
p.start() # no target scheme and no parent blocking by join
while True: # this is the main application loop
sleep(2)
print 'In main loop doing something independant from the rest'
这是我得到的:
Main process gets data from queue: (0,)
Main process gets data from queue: (1,)
Main process gets data from queue: (2,)
Main process gets data from queue: (3,)
In main loop doing something independant from queue management
Main process gets data from queue: (4,)
Main process gets data from queue: (5,)
Main process gets data from queue: (6,)
Main process gets data from queue: (7,)
In main loop doing something independant from queue management
Main process gets data from queue: (8,)
Main process gets data from queue: (9,)
In main loop doing something independant from queue management
...
答案 0 :(得分:0)
一般观察:
类MyChildProcess
您不需要为子进程和侦听器线程创建单独的类。简单的功能可以工作。
<强> pollQueue 强>
您可以在侦听器线程中使用阻塞get()调用。这将使该线程更有效。
关闭
你可以用一个信号杀死一个进程,但杀死一个线程更难(真的不可能)。你的关机 例程将取决于您希望如何处理仍在队列中的项目。
如果您不关心在关闭时处理队列中剩余的项目,您可以
只需向子进程发送一个TERM信号并退出主线程。自从听众
线程将.daemon
属性设置为True,它也将退出。
如果你关心在关机时处理队列中的项目,你应该这样做 通过发送特殊的 sentinel 值通知侦听器线程退出其处理循环 然后加入该线程等待它退出。
这是一个包含上述想法的例子。我没有选择None
哨兵价值。
#!/usr/bin/env python
from threading import Thread
from multiprocessing import Process, Queue
from time import sleep
from random import random
import os
import signal
def child_process(q):
i = 1
while True:
q.put(i)
i += 1
sleep( random() )
def listener_thread(q, callback):
while True:
item = q.get() # this will block until an item is ready
if item is None:
break
callback(item)
def doit(item):
print "got:", item
def main():
q = Queue()
# start up the child process:
child = Process(target=child_process, args=(q,))
child.start()
# start up the listener
listener = Thread(target=listener_thread, args=(q,doit))
listener.daemon = True
listener.start()
sleep(5)
print "Exiting"
os.kill( child.pid, signal.SIGTERM )
q.put(None)
listener.join()
main()