Python Multiprocessing Pool.map在_new中导致错误__

2024-06-16 09:19:35 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面的简单Python 3示例中,我们使用multiproessing模块处理列表friends,是什么导致了错误:

TypeError: new() missing 1 required positional argument: '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'

Tags: nameinpyselffriendnewlibmultiprocessing
2条回答

定义__reduce__以使Friend类的对象可pickle化(可序列化)以发送到其他进程

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)

取消勾选期间出错,因为在取消勾选期间重新创建对象时,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()

This method serves a similar purpose as getnewargs_ex(), but supports only positional arguments. It must return a tuple of arguments args which will be passed to the new() method upon unpickling.

getnewargs() will not be called if getnewargs_ex() is defined.

Changed in version 3.6: Before Python 3.6, getnewargs() was called instead of getnewargs_ex() in protocols 2 and 3.

因此,在你的情况下:

def __getnewargs__(self):
    return self.name,

相关问题 更多 >