7

Tring do użycia multiprocessing w moim kodzie dla lepszej wydajności.Czy mogę użyć narzędzia wieloprocesorowego w metodzie klasy?

Jednak mam błąd w następujący sposób:

Traceback (most recent call last): 
    File "D:\EpubBuilder\TinyEpub.py", line 49, in <module> 
    e.epub2txt() 
    File "D:\EpubBuilder\TinyEpub.py", line 43, in epub2txt 
    tempread = self.get_text() 
    File "D:\EpubBuilder\TinyEpub.py", line 29, in get_text 
    txtlist = pool.map(self.char2text,charlist) 
    File "C:\Python34\lib\multiprocessing\pool.py", line 260, in map 
    return self._map_async(func, iterable, mapstar, chunksize).get() 
    File "C:\Python34\lib\multiprocessing\pool.py", line 599, in get 
    raise self._value 
    File "C:\Python34\lib\multiprocessing\pool.py", line 383, in _handle_tasks 
    put(task) 
    File "C:\Python34\lib\multiprocessing\connection.py", line 206, in send 
    self._send_bytes(ForkingPickler.dumps(obj)) 
    File "C:\Python34\lib\multiprocessing\reduction.py", line 50, in dumps 
    cls(buf, protocol).dump(obj) 
TypeError: cannot serialize '_io.BufferedReader' object 

Próbowałem mu inną drogę i mam ten błąd:

TypeError: cannot serialize '_io.TextIOWrapper' object 

Mój kod wygląda następująco:

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) 

Myślę, że błąd został zgłoszony z powodu nie używania Pool w głównej funkcji.

Czy moje przypuszczenia są słuszne? I jak mogę zmodyfikować mój kod, aby naprawić błąd?

+0

Co mówi "type (charlist [0])? Jest to nieco mylące, ponieważ Twój komunikat o błędzie jest niezgodny z opublikowanym przez Ciebie kodem. ('char2text' vs.' format_char'). –

+0

@JohnZwinck Mój prawdziwy kod jest dość długi, a kod tutaj jest uproszczony. Jeśli wygląda na zagmatwany, będę edytować it.type (charlist [0]) is 'string' – PaleNeutron

Odpowiedz

16

Problem polega na tym, że w instancji Book znajduje się niepodobna zmienna instancji (namelist). Ponieważ wywołujesz metodę pool.map w metodzie instancji i pracujesz w systemie Windows, cała instancja musi być możliwa do wybrania, aby mogła zostać przekazana do procesu potomnego. Book.namelist to obiekt z otwartym plikiem (_io.BufferedReader), którego nie można usunąć. Możesz to naprawić na kilka sposobów. Na podstawie kodu przykład, wygląda jak można po prostu zrobić format_char funkcję najwyższego poziomu:

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 

Jednakże, jeśli w rzeczywistości, trzeba format_char się metodę instancji, można użyć __getstate__/__setstate__ aby Book picklable , usuwając namelist argument z instancji przed trawieniu go:

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 

To byłoby ok, dopóki nie potrzebują dostępu namelist w procesie potomnym.

+0

Dzięki! Teraz działa dobrze, a moje przypuszczenia są błędne. – PaleNeutron

Powiązane problemy