【问题标题】:Can't return appended value from within a Python process无法从 Python 进程中返回附加值
【发布时间】:2010-12-02 19:00:14
【问题描述】:

我在 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 运行完全相同的代码时,我可以毫无问题地获得所需的输出,这让我相信这是内存共享的问题。

【问题讨论】:

  • 请修正您的代码格式 - 对于 Python 代码来说,查看事物的缩进方式尤为重要。
  • 使用类似 AMPQ 的东西可以很容易地在服务器之间分配工作。
  • 你考虑过使用multiprocessing.Queues吗?

标签: python list process append


【解决方案1】:

当您使用单独的进程时,每个进程都会在内存中获取自己的所有内容副本。这就是为什么父进程在其outputs 中看不到任何内容的原因:每个子进程都附加到自己的outputs 副本。

您需要使用某种形式的进程间通信。 Python 的 multiprocessing 库为此提供了两个功能:pipes and queues

例如,使用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'

【讨论】:

  • Programming Guidelines - All Platformsmultiprocessing 模块的标题为“加入使用队列的进程”的小节中,它建议“无论何时使用队列,都需要确保所有具有被放入队列的最终将在进程加入之前被移除”。我相信这意味着此答案的代码中的 q.get() 应该移到 before p.join() 之前,就像他们在文档中的示例中显示的那样。
  • 好点。 (不过,文档可能会在有关管道和队列的部分中提到这一点。)
【解决方案2】:

multiprocessingmodule 的在线文档中标题为Exchanging objects between processes 的部分说它[仅]“支持进程之间的两种类型的通信通道”并继续提到队列管道。值得注意的是,它没有提到listobjects likeoutputs1。这是有道理的,因为这两个进程不共享内存 AFAIK。

我不确定,但我也怀疑您可能需要将创建进程并启动它的代码部分等放在if __name__ == '__main__':clause 中,以防止子进程创建子子进程。

总而言之,我认为您将不得不重新设计一些东西以使用这两个中的一个进行进程间通信——队列对我来说似乎是合乎逻辑的选择。

【讨论】:

    猜你喜欢
    • 2018-05-19
    • 2018-08-07
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 2015-09-24
    • 2018-07-03
    • 2017-08-22
    • 2017-12-23
    相关资源
    最近更新 更多