如何更改Python multiprocessing
库使用的序列化方法?特别是,默认的序列化方法使用pickle
库和该版本的Python的默认pickle协议版本。默认的pickle协议是Python 2.7中的版本2和Python 3.6中的版本3。如何在Python 3.6中将协议版本设置为2,因此我可以使用Client
库中的某些类(如Listener
和multiprocessing
)在服务器处理运行之间进行通信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
。
答案 0 :(得分:2)
如果您使用多处理"context" object,我相信您所指的补丁有效。
使用你的pickle2reducer.py,你的客户应该从:
开始import pickle2reducer
import multiprocessing as mp
ctx = mp.get_context()
ctx.reducer = pickle2reducer.Pickle2Reducer()
ctx
与multiprocessing
具有相同的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
类来做同样的事情。