Dalam contoh Python 3 sederhana di bawah ini di mana kita menggunakan modul multiproessing untuk memproses daftar friends, apa yang menyebabkan kesalahan:

TypeError: new() hilang 1 argumen posisi yang diperlukan: 'name'

Tidak ada kesalahan yang terjadi jika hanya menjalankan

tom = Friend(tom)
say_hello(tom)

Adakah ide bagaimana kita bisa menyelesaikan masalah ini? Terima kasih!

Kode

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)

Pelacakan Kesalahan Penuh

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'
3
Nyxynyx 20 Januari 2020, 20:43

2 jawaban

Jawaban Terbaik

Ini adalah kesalahan selama unpickling karena name tidak siap untuk dilewatkan saat membuat ulang objek selama unpickling.

Itu sudah dapat direproduksi dengan:

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'

Solusinya adalah dengan mengimplementasikan object.__getnewargs__() atau < a href="https://docs.python.org/3/library/pickle.html#object.__getnewargs_ex__" rel="nofollow noreferrer"object.__getnewargs_ex__().

objek.getnewwargs()

Metode ini memiliki tujuan yang sama dengan getnewargs_ex(), tetapi hanya mendukung argumen posisi. Itu harus mengembalikan satu tuple dari argumen argumen yang akan diteruskan ke metode baru() pada saat membongkar.

getnewargs() tidak akan dipanggil jika getnewargs_ex() didefinisikan.

Diubah di versi 3.6: Sebelum Python 3.6, getnewargs() dipanggil alih-alih getnewargs_ex() dalam protokol 2 dan 3.

Jadi dalam kasus Anda:

def __getnewargs__(self):
    return self.name,
2
Darkonaut 20 Januari 2020, 18:36

Definisikan __reduce__ untuk membuat objek kelas Friend dapat diambil (serializable) untuk dikirim ke proses lain.

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)
1
Saim Raza 20 Januari 2020, 18:42