Python 多处理 vs time.sleep 主进程挂起子进程
Python multiprocessing vs time.sleep on main process hang child process
我正在尝试使用 python 2.7 中的多处理库,我发现 time.sleep() 函数的行为有点令人不安。我需要控制一个时序关键硬件(在 Raspberry PI 上),我最初的目标是使用这个库使用一个专用于此的进程。但是我发现让主进程休眠(time.sleep)也会让子进程休眠!?!?这是正常行为还是我遗漏了什么?这是重现我的问题的代码示例:
import time
from multiprocessing import Process, Queue
def child(q_display):
c = 9999999
while True:
data = q_display.get()
print data
print c
c = c - 1
if __name__ == '__main__':
q_display = Queue()
p = Process(target=child, args=(q_display,)).start()
data = 1
try:
while True:
q_display.put(data)
data = data + 1
print "MAIN ***********************************"
time.sleep(1)
except KeyboardInterrupt:
print "Keyboard CTRL-C !!!"
输出是这样的:
MAIN ***********************************
1
9999999
MAIN ***********************************
2
9999998
MAIN ***********************************
3
9999997
MAIN ***********************************
4
9999996
MAIN ***********************************
5
9999995
MAIN ***********************************
6
9999994
但这正是我所期望的:
MAIN ***********************************
1
9999999
9999998
9999997
9999996
9999995
9999994
9999993
9999992
MAIN ***********************************
2
9999991
9999990
9999989
9999988
9999987
9999986
9999985
9999984
... etc
我做错了什么?
我认为问题在于您正在将数据放入队列的循环中休眠。所以在你的主进程休眠之前队列中只有一个值,因此子进程在阻塞之前只能读出一个值。
问题是 Queue.get()
阻塞,直到队列中有可用的项目。通过将超时参数传递给 get()
函数,并捕获相应的错误(这需要一个 from Queue import Empty
),即使主进程尚未发送任何内容,您也可以继续在子进程中做其他事情.将子函数中的代码更改为:
while True:
try:
data = q_display.get(True, timeout=0.1) # can raise Empty after 0.1 s
print data
except Empty: # queue was empty, next time better
pass
print c
c = c - 1
这似乎或多或少做了你想要的:
MAIN ***********************************
MAIN ***********************************1
9999999
[...]
9999990
2
MAIN ***********************************
9999989
9999988
[...]
9999980
3
MAIN ***********************************
9999979
[...]
9999970
4
MAIN ***********************************
9999969
[...]
9999960
5
MAIN ***********************************
9999959
[...]
9999950
6
Keyboard CTRL-C !!!
9999949
[...]
9999943
请注意,主进程和子进程的打印输出可能会有些混乱,由于缓冲问题,它们不是监视事件确切时间的准确方法。
我正在尝试使用 python 2.7 中的多处理库,我发现 time.sleep() 函数的行为有点令人不安。我需要控制一个时序关键硬件(在 Raspberry PI 上),我最初的目标是使用这个库使用一个专用于此的进程。但是我发现让主进程休眠(time.sleep)也会让子进程休眠!?!?这是正常行为还是我遗漏了什么?这是重现我的问题的代码示例:
import time
from multiprocessing import Process, Queue
def child(q_display):
c = 9999999
while True:
data = q_display.get()
print data
print c
c = c - 1
if __name__ == '__main__':
q_display = Queue()
p = Process(target=child, args=(q_display,)).start()
data = 1
try:
while True:
q_display.put(data)
data = data + 1
print "MAIN ***********************************"
time.sleep(1)
except KeyboardInterrupt:
print "Keyboard CTRL-C !!!"
输出是这样的:
MAIN ***********************************
1
9999999
MAIN ***********************************
2
9999998
MAIN ***********************************
3
9999997
MAIN ***********************************
4
9999996
MAIN ***********************************
5
9999995
MAIN ***********************************
6
9999994
但这正是我所期望的:
MAIN ***********************************
1
9999999
9999998
9999997
9999996
9999995
9999994
9999993
9999992
MAIN ***********************************
2
9999991
9999990
9999989
9999988
9999987
9999986
9999985
9999984
... etc
我做错了什么?
我认为问题在于您正在将数据放入队列的循环中休眠。所以在你的主进程休眠之前队列中只有一个值,因此子进程在阻塞之前只能读出一个值。
问题是 Queue.get()
阻塞,直到队列中有可用的项目。通过将超时参数传递给 get()
函数,并捕获相应的错误(这需要一个 from Queue import Empty
),即使主进程尚未发送任何内容,您也可以继续在子进程中做其他事情.将子函数中的代码更改为:
while True:
try:
data = q_display.get(True, timeout=0.1) # can raise Empty after 0.1 s
print data
except Empty: # queue was empty, next time better
pass
print c
c = c - 1
这似乎或多或少做了你想要的:
MAIN ***********************************
MAIN ***********************************1
9999999
[...]
9999990
2
MAIN ***********************************
9999989
9999988
[...]
9999980
3
MAIN ***********************************
9999979
[...]
9999970
4
MAIN ***********************************
9999969
[...]
9999960
5
MAIN ***********************************
9999959
[...]
9999950
6
Keyboard CTRL-C !!!
9999949
[...]
9999943
请注意,主进程和子进程的打印输出可能会有些混乱,由于缓冲问题,它们不是监视事件确切时间的准确方法。