Python队列突然空了
我正试图根据这些数据同时进行一些计算。我对它进行了扩展,不再只是一个简单的函数,而是通过子流程运行一些外部软件。它在Ubuntu 14.04.2 LTS GNU/Linux 3.16.0-30-generic x86_64上使用Python 2.7.6运行 有一个队列用于跟踪结果输出。这个队列应该被填满,但在计算完成后似乎是空的 简化的代码如下所示:Python队列突然空了,python,python-2.7,subprocess,python-multiprocessing,Python,Python 2.7,Subprocess,Python Multiprocessing,我正试图根据这些数据同时进行一些计算。我对它进行了扩展,不再只是一个简单的函数,而是通过子流程运行一些外部软件。它在Ubuntu 14.04.2 LTS GNU/Linux 3.16.0-30-generic x86_64上使用Python 2.7.6运行 有一个队列用于跟踪结果输出。这个队列应该被填满,但在计算完成后似乎是空的 简化的代码如下所示: import subprocess, shlex, os, random, pickle from Queue import Queue from
import subprocess, shlex, os, random, pickle
from Queue import Queue
from multiprocessing import Process
from time import sleep
def mp_solve(problems, nprocs):
def worker(problem, out_q):
outdict = []
cmd = "..." + problem
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
outdict = [str(problem), str(output)]
out_q.put(outdict)
print out_q.empty() #prints False
out_q = Queue() #create Queue
procs = []
for i in range(nprocs):
p = Process(
target=worker,
args=(problems[i][1], out_q))
procs.append(p)
p.start()
sleep(10) #calculations are limited to 3 seconds through a parameter passed to external program
print out_q.empty() #prints True
resultlist = []
for i in range(nprocs):
print "going to Q" + str(i)
try:
resultlist.append(out_q.get())
except Queue.Empty:
print "Queue empty"
mp_solve(list_of_problems, 10)
这个的输出将是
False
False
False
False
False
False
False
False
False
False
True
going to Q0
在最后一个命令之后,会话窗口将变得无用。我可以输入它,但什么也不会发生,甚至Ctrl+C也没有效果。然后,我只需关闭ssh会话
我是多道处理的新手,我不明白为什么从返回的False中可以看到队列被正确填充,但随后却是空的。请注意,Queue.Empty似乎永远不会被捕获。你知道如何让我回到正确的轨道上吗?队列模块中的队列对象不适用于多处理:它只用于同一进程中线程之间的通信。改用多处理模块中的队列对象
from multiprocessing import Process, Queue
这应该解决眼前的问题。以下是一些其他注意事项:
out_q.get是一个阻塞调用:如果队列中没有任何内容,那么它将等待,直到有内容为止。因此,在上面的代码中,将永远不会引发空异常。对于非阻塞版本,请尝试_q.getblock=False。或者,您可以指定一个超时:out_q.gettimeout=10.0
最好在主进程退出之前加入子进程。对每个进程调用proc.join。正如dano在评论中指出的那样,如果您在清空队列之前尝试加入进程(请参见警告),则可能会出现死锁,因此您可能希望在mp_solve函数的末尾执行此操作
使用if uuu name uuu=='uuuu main uuuu':块保护主代码也是一种很好的做法。它在Python 2.7下的Linux上不会有什么不同,但是如果没有它,您的代码将无法在Windows上正确运行
同样,为了实现跨平台兼容性,您应该将嵌套的辅助函数移出到模块级。要使代码在Windows上运行,辅助函数需要是可pickle的,而嵌套函数则不可pickle
队列模块中的队列对象不适用于多处理:它仅用于同一进程中线程之间的通信。改用多处理模块中的队列对象
from multiprocessing import Process, Queue
这应该解决眼前的问题。以下是一些其他注意事项:
out_q.get是一个阻塞调用:如果队列中没有任何内容,那么它将等待,直到有内容为止。因此,在上面的代码中,将永远不会引发空异常。对于非阻塞版本,请尝试_q.getblock=False。或者,您可以指定一个超时:out_q.gettimeout=10.0
最好在主进程退出之前加入子进程。对每个进程调用proc.join。正如dano在评论中指出的那样,如果您在清空队列之前尝试加入进程(请参见警告),则可能会出现死锁,因此您可能希望在mp_solve函数的末尾执行此操作
使用if uuu name uuu=='uuuu main uuuu':块保护主代码也是一种很好的做法。它在Python 2.7下的Linux上不会有什么不同,但是如果没有它,您的代码将无法在Windows上正确运行
同样,为了实现跨平台兼容性,您应该将嵌套的辅助函数移出到模块级。要使代码在Windows上运行,辅助函数需要是可pickle的,而嵌套函数则不可pickle
看起来你有一个叉子炸弹。你有没有在所有的多处理示例中看到if uuuu name uuuuuuu='.\uuuuu main uuuuuuuu'这个词?你在哪里调用mp_solve?可能是重复的@ReutSharabani:这不是特定于使用Pool吗?@cdarke,据我所知不是。其思想是进行某种装箱,将对象全球化到其他进程。据我所知,任何其他过程。但我可能错了。看起来你有一个叉子炸弹。你有没有在所有的多处理示例中看到if uuuu name uuuuuuu='.\uuuuu main uuuuuuuu'这个词?你在哪里调用mp_solve?可能是重复的@ReutSharabani:这不是特定于使用Pool吗?@cdarke,据我所知不是。其思想是进行某种装箱,将对象全球化到其他进程。据我所知,任何其他过程。但我可能错了。第二点需要注意的是,如果您的子进程将大量数据放入输出队列,则在将数据从队列中取出之前尝试加入子进程可能会导致死锁。看到警告了吗?@dano:我忘了那个细节了。谢谢。请注意第二点-如果您的子进程将大量数据放入输出队列,则在将数据从队列中拉出之前尝试加入子进程可能会导致死锁。看到警告了吗?@dano:我会的 我对那个细节感到惊讶。谢谢