无法从 Python 进程内部返回追加的值

1 投票
2 回答
1077 浏览
提问于 2025-04-16 07:56

我在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'

撰写回答