无法从 Python 进程内部返回追加的值
我在Ubuntu 8.10上运行的是Python 2.6.5。
我正在做一个项目,需要同时运行几个进程,并把每个进程的输出保存到各自的列表里。因为我不能直接从进程中返回输出值,所以我把输出列表作为参数传给目标函数,然后把输出添加到那个列表里。问题是,当我尝试在运行进程后访问那个列表时,发现列表还是空的。下面是我遇到的问题的简化版本,还有错误信息。
代码:
from multiprocessing import Process
import sys, math, os,commands
outputs = []
def calculate(a,b,outputs):
c = a*b
outputs.append(c)
#return c
outputs1 = []
p1 = Process(target = calculate, args = (2,3,outputs1))
p1.start()
p1.join()
print 'len(outputs1) = ' + str(len(outputs1))
print 'outputs1 = ' + str(outputs1[0])
错误信息:
len(outputs1) = 0
Traceback (most recent call last):
File "append_test.py", line 23, in <module>
print 'outputs1 = ' + str(outputs1[0])
IndexError: list index out of range
我想让每个进程完全独立,以免数据被破坏。我尝试使用多进程的Array模块,但发现append方法是特定于列表的。当我用线程(Thread)代替进程(Process)运行完全相同的代码时,能得到想要的输出,没有问题,这让我觉得这是一个内存共享的问题。
2 个回答
0
在multiprocessing
模块的在线文档中,有一部分叫做进程间对象交换,里面提到它“只支持两种进程间的通信方式”,这两种方式是队列和管道。值得注意的是,它并没有提到像outputs1
这样的list
对象。这是有道理的,因为我知道这两个进程并不共享内存。
我不太确定,但我也怀疑你可能需要把创建和启动进程的那部分代码放在if __name__ == '__main__':
这个条件语句里面,以防止子进程再创建子进程。
总的来说,我觉得你需要重新调整一下代码,使用这两种方式中的一种来进行进程间的通信——在我看来,队列是比较合理的选择。
3
当你使用不同的进程时,每个进程都有自己的一份内存拷贝。这就是为什么父进程看不到它的outputs
里的任何内容:每个子进程都在往自己那份outputs
里添加数据。
你需要使用某种进程间通信的方法。Python的multiprocessing
库提供了两种功能来实现这一点:管道和队列。
例如,使用Queue
:
>>> from multiprocessing import Process, Queue
>>> def f(q): q.put("hello from the child process")
...
>>> q = Queue()
>>> p = Process(target=f, args=(q,))
>>> p.start()
>>> p.join()
>>> q.get()
'hello from the child process'