python - 多处理忽略 "__setstate__"

标签 python multiprocessing pickle python-multiprocessing

我假设 multiprocessing 包使用 pickle 在进程之间发送东西。但是,pickle 会注意对象的 __getstate____setstate__ 方法。多处理似乎忽略了它们。它是否正确?我糊涂了吗?

要复制,安装 docker,然后输入命令行

$ docker run python:3.4 python -c "import pickle
import multiprocessing
import os

class Tricky:
    def __init__(self,x):
        self.data=x

    def __setstate__(self,d):
        self.data=10

    def __getstate__(self):
        return {}

def report(ar,q):
    print('running report in pid %d, hailing from %d'%(os.getpid(),os.getppid()))
    q.put(ar.data)

print('module loaded in pid %d, hailing from pid %d'%(os.getpid(),os.getppid()))
if __name__ == '__main__':
    print('hello from pid %d'%os.getpid())
    ar = Tricky(5)
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=report, args=(ar, q))
    p.start()
    p.join()
    print(q.get())
    print(pickle.loads(pickle.dumps(ar)).data)"

你应该得到类似的东西

module loaded in pid 1, hailing from pid 0
hello from pid 1
running report in pid 5, hailing from 1
5
10

我本以为应该是“10”“10”,但实际上是“5”“10”。这意味着什么?

(注意:根据 user3667217 的建议编辑代码以符合编程指南)

最佳答案

多处理模块可以通过以下三种方式之一启动:spawn、fork 或 forkserver。默认情况下,在 unix 上,它会 fork 。这意味着在新进程诞生时不需要 pickle 任何已经加载到 ram 中的东西。

如果您需要更直接地控制 fork 的发生方式,您需要将启动设置更改为 spawn。为此,创建一个上下文

ctx=multiprocessing.get_context('spawn')

并将所有对 multiprocessing.foo() 的调用替换为对 ctx.foo() 的调用。当你这样做时,每个新进程都会作为一个新的 python 实例诞生;发送到其中的所有内容都将通过 pickle 发送,而不是直接 memcopy。

关于python - 多处理忽略 "__setstate__",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33685329/

相关文章:

python - 杀死启动时启动的 python 进程

Python线程和多处理错误?

python - 如何获取Python函数的pickle依赖项?

python - 序列化具有依赖项的 python 函数

python - 序列化/挑选一个在字符串中定义的函数

python - 通过 Youtube 上传,通过 api 设置为私有(private)(锁定)

python - 如何使用 Mediapipe Pose 更改输出视频上的跟踪点和连接线的颜色?

python - 按层次结构从许多字典中获取值

python - 使用 python 多处理模块创建的子进程不会打印

python - 为什么我的多进程队列看起来不是线程安全的?