如何更改Python的多处理使用的序列化方法?

时间:2017-07-15 14:02:00

标签: python serialization python-multiprocessing

如何更改Python multiprocessing库使用的序列化方法?特别是,默认的序列化方法使用pickle库和该版本的Python的默认pickle协议版本。默认的pickle协议是Python 2.7中的版本2和Python 3.6中的版本3。如何在Python 3.6中将协议版本设置为2,因此我可以使用Client库中的某些类(如Listenermultiprocessing)在服务器处理运行之间进行通信Python 2.7和Python 3.6运行的客户端进程?

(旁注:作为测试,我通过将protocol=2添加到dump()调用来修改line 206 of multiprocessing/connection.py,以强制协议版本为2,并且我的客户端/服务器进程在我的限制中工作使用服务器运行2.7和客户端运行3.6)。

在Python 3.6中,合并patch以设置序列化程序,但补丁未记录,我还没弄清楚如何使用它。以下是我尝试使用它的方法(我也将其发布到我链接到的Python票证中):

pickle2reducer.py:

from multiprocessing.reduction import ForkingPickler, AbstractReducer

class ForkingPickler2(ForkingPickler):
    def __init__(self, *args):
        if len(args) > 1:
            args[1] = 2
        else:
            args.append(2)
        super().__init__(*args)

    @classmethod
    def dumps(cls, obj, protocol=2):
        return ForkingPickler.dumps(obj, protocol)


def dump(obj, file, protocol=2):
    ForkingPickler2(file, protocol).dump(obj)


class Pickle2Reducer(AbstractReducer):
    ForkingPickler = ForkingPickler2
    register = ForkingPickler2.register
    dump = dump

在我的客户中:

import pickle2reducer
multiprocessing.reducer = pickle2reducer.Pickle2Reducer()

在使用multiprocessing执行任何其他操作之前在顶部。当我这样做时,我仍然在Python 2.7上运行的服务器上看到ValueError: unsupported pickle protocol: 3

2 个答案:

答案 0 :(得分:2)

如果您使用多处理"context" object,我相信您所指的补丁有效。

使用你的pickle2reducer.py,你的客户应该从:

开始
import pickle2reducer
import multiprocessing as mp

ctx = mp.get_context()
ctx.reducer = pickle2reducer.Pickle2Reducer()

ctxmultiprocessing具有相同的API。

希望有所帮助!

答案 1 :(得分:0)

非常感谢。它使我完全找到了我需要的解决方案。我最终做了类似的事情,但通过修改 Connection 类。对我来说,这比创建自己的完整子类并替换它更干净。

from multiprocessing.connection import Connection, _ForkingPickler, Client, Listener

def send_py2(self, obj):
    self._check_closed()
    self._check_writable()
    self._send_bytes(_ForkingPickler.dumps(obj, protocol=2))

Connection.send = send_py2

这正是来自 multiprocessing.connection 的代码,仅添加了 protocol=2 参数。

我想您甚至可以通过直接编辑 multiprocessing.reduction 中的原始 ForkingPickler 类来做同样的事情。