Python multiprocessing.Process: 从局部变量开始

Python multiprocessing.Process: start with local variable

我正在努力理解 multiprocessing.Process class。我想异步收集数据并将其存储在某处。存储数据后,它会以某种方式丢失。这是我的 MWE:

from __future__ import print_function
import multiprocessing as mp

def append_test(tgt):
    tgt.append(42)
    print('Appended:', tgt)

l = []
p = mp.Process(target=lambda: append_test(l))

p.run()
print('l is', l)

p.start()
p.join()
print('l is', l)

如果我运行宁那个片段,我得到

Appended: [42]
l is [42]
Appended: [42, 42]
l is [42]

如您所见,调用 运行 和使用 start/join 是有区别的。它与订单无关(之后使用 运行)-我试过了。有人可以详细说明第二个 42 是如何丢失的吗?好像是在某个时候存储的?但在其他时候肯定不是。

以防万一可能会有所不同:我已经尝试了 python2.7 和 python3.4,两者的结果与上述完全相同。


Update:显然只启动一个新进程,之后将调用 运行。然后我的实际问题转化为以下问题:如何将 l 传递给衍生进程 s.t。我能看到实际结果吗?


解决方案:以下示例显示如何将共享数据安全地传递给进程:

from __future__ import print_function
import multiprocessing as mp

def append_test(tgt):
    tgt.append(42)
    print('Appended:', tgt)

m = mp.Manager()
l = m.list()
p = mp.Process(target=lambda: append_test(l))

p.start()
p.join()
print('l is', l)

进一步阅读:Multiprocessing Managers Documentation

运行 执行您在多处理中定位的可调用对象。 Start 将为该对象调用 运行() 方法。

来自multiprocessing's documentation

run() Method representing the process’s activity.

您可以在子类中覆盖此方法。标准 运行() 方法 调用传递给对象构造函数的可调用对象作为 目标参数,如果有的话,采用顺序和关键字参数 分别来自 args 和 kwargs 参数。

start() 启动进程的activity.

每个进程对象最多只能调用一次。它安排了 要在单独进程中调用的对象的 运行() 方法。

来自 Python:Beazley 的基本参考资料:

p.run():进程启动时运行的方法。默认情况下,这会调用传递给 Process 构造函数的目标。 ...

p.start():启动进程。这将启动代表流程的子流程并在该子流程中调用 p.run()。

所以,他们不应该做同样的事情。在我看来,在这种情况下,正在为正在进行的进程调用 p.run() 并且 p.start() 在新进程中调用 p.run() 并传递原始目标到构造函数(其中 l 仍然是 [ ])。