Могу ли я использовать многопроцессорную обработку.Пул в методе класса?
Я пытаюсь использовать multiprocessing
в моем коде для лучшей производительности.
тем не менее, я получил ошибку следующим образом:
Traceback (most recent call last):
File "D:EpubBuilderTinyEpub.py", line 49, in <module>
e.epub2txt()
File "D:EpubBuilderTinyEpub.py", line 43, in epub2txt
tempread = self.get_text()
File "D:EpubBuilderTinyEpub.py", line 29, in get_text
txtlist = pool.map(self.char2text,charlist)
File "C:Python34libmultiprocessingpool.py", line 260, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "C:Python34libmultiprocessingpool.py", line 599, in get
raise self._value
File "C:Python34libmultiprocessingpool.py", line 383, in _handle_tasks
put(task)
File "C:Python34libmultiprocessingconnection.py", line 206, in send
self._send_bytes(ForkingPickler.dumps(obj))
File "C:Python34libmultiprocessingreduction.py", line 50, in dumps
cls(buf, protocol).dump(obj)
TypeError: cannot serialize '_io.BufferedReader' object
я попробовал это по-другому и получил эту ошибку:
TypeError: cannot serialize '_io.TextIOWrapper' object
мой код выглядит так:
from multiprocessing import Pool
class Book(object):
def __init__(self, arg):
self.namelist = arg
def format_char(self,char):
char = char + "a"
return char
def format_book(self):
self.tempread = ""
charlist = [f.read() for f in self.namelist] #list of char
with Pool() as pool:
txtlist = pool.map(self.format_char,charlist)
self.tempread = "".join(txtlist)
return self.tempread
if __name__ == '__main__':
import os
b = Book([open(f) for f in os.listdir()])
t = b.format_book()
print(t)
Я думаю, что ошибка возникает из-за не используя Pool
в главном функции.
верно ли мое предположение? И как я могу изменить свой код, чтобы исправить ошибку?
1 ответов
проблема в том, что у вас есть непиклируемая переменная экземпляра (namelist
) в Book
экземпляра. Потому что ты звонишь pool.map
в методе экземпляра, и вы работаете в Windows, весь экземпляр должен быть picklable для того, чтобы он был передан дочернему процессу. Book.namelist
- открытый файловый объект (_io.BufferedReader
), который нельзя мариновать. Вы можете исправить это несколькими способами. Основываясь на примере кода, похоже, вы можете просто сделать format_char
топ-уровня функция:
def format_char(char):
char = char + "a"
return char
class Book(object):
def __init__(self, arg):
self.namelist = arg
def format_book(self):
self.tempread = ""
charlist = [f.read() for f in self.namelist] #list of char
with Pool() as pool:
txtlist = pool.map(format_char,charlist)
self.tempread = "".join(txtlist)
return self.tempread
однако, если на самом деле, вам нужно format_char
чтобы быть методом экземпляра, вы можете использовать __getstate__
/__setstate__
сделать Book
picklable, путем извлекать namelist
аргумент от экземпляра перед его маринованием:
class Book(object):
def __init__(self, arg):
self.namelist = arg
def __getstate__(self):
""" This is called before pickling. """
state = self.__dict__.copy()
del state['namelist']
return state
def __setstate__(self, state):
""" This is called while unpickling. """
self.__dict__.update(state)
def format_char(self,char):
char = char + "a"
def format_book(self):
self.tempread = ""
charlist = [f.read() for f in self.namelist] #list of char
with Pool() as pool:
txtlist = pool.map(self.format_char,charlist)
self.tempread = "".join(txtlist)
return self.tempread
это было бы нормально, пока вам не нужно получить доступ namelist
в дочернем процессе.