在下面的简单Python 3示例中,我们使用multiproessing
模块处理列表friends
,导致错误的原因:
类型错误:new(( 缺少 1 个必需的位置参数:"name">
如果只是运行,则不会发生错误
tom = Friend(tom)
say_hello(tom)
任何想法我们如何解决这个问题?谢谢!
法典
import multiprocessing
def say_hello(friend):
print('Hello', friend.name, '!')
class Friend:
friends = {}
def __new__(cls, name):
if name not in cls.friends:
cls.friends[name] = super(Friend, cls).__new__(cls)
return cls.friends[name]
def __init__(self, name):
self.name = name
jack = Friend('jack')
ryan = Friend('ryan')
friends = [jack, ryan]
multiprocessing.Pool(2).map(say_hello, friends)
完整错误跟踪
Traceback (most recent call last):
File "/Users/nyxynyx/opt/anaconda3/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
self.run()
File "/Users/nyxynyx/opt/anaconda3/lib/python3.7/multiprocessing/process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "/Users/nyxynyx/opt/anaconda3/lib/python3.7/multiprocessing/pool.py", line 110, in worker
task = get()
File "/Users/nyxynyx/opt/anaconda3/lib/python3.7/multiprocessing/queues.py", line 354, in get
return _ForkingPickler.loads(res)
TypeError: __new__() missing 1 required positional argument: 'name'
这是取消搌制期间的错误,因为在取消搌制期间重新创建对象时,name
未准备好传递。
它已经可以通过以下方式复制:
pickle.loads(pickle.dumps(jack))
Traceback (most recent call last):
...
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-9-239857af5731>", line 1, in <module>
pickle.loads(pickle.dumps(jack))
TypeError: __new__() missing 1 required positional argument: 'name'
解决方案是实施object.__getnewargs__()
或object.__getnewargs_ex__()
。
对象。Getnewargs((
此方法的作用与getnewargs_ex(( 类似,但 仅支持位置参数。它必须返回一个元组 参数参数,将传递给new(( 方法 脱腌。
如果定义了getnewargs_ex((,则不会调用getnewargs((。
在 3.6 版更改: 在 Python 3.6 之前,getnewargs(( 被调用 而不是协议 2 和 3 中的getnewargs_ex((。
所以在你的情况下:
def __getnewargs__(self):
return self.name,
定义__reduce__
以使Friend
类的对象可pickleable(可序列化(发送到其他进程。
import multiprocessing
def say_hello(friend):
print('Hello', friend.name, '!')
class Friend:
friends = {}
def __new__(cls, name):
if name in cls.friends:
return cls.friends[name]
else:
return super(Friend, cls).__new__(cls)
def __init__(self, name):
self.name = name
def __reduce__(self):
return self.__class__, (self.name,)
jack = Friend('jack')
ryan = Friend('ryan')
friends = [jack, ryan]
multiprocessing.Pool(2).map(say_hello, friends)