7

Ich bin dran, multiprocessing in meinem Code für eine bessere Leistung zu verwenden.Kann ich multiprocessing.Pool in einer Methode einer Klasse verwenden?

jedoch bekam ich einen Fehler wie folgt:

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 

Ich habe es eine andere Art und Weise versucht, und habe diesen Fehler:

TypeError: cannot serialize '_io.TextIOWrapper' object 

Mein Code sieht wie folgt aus:

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) 

Ich denke, dass der Fehler ausgelöst wird, weil die in der Hauptfunktion nicht verwendet wird.

Ist meine Vermutung richtig? Und wie kann ich meinen Code ändern, um den Fehler zu beheben?

+0

Was sagt 'type (charlist [0])'? Und es ist ein wenig verwirrend, weil Ihre Fehlermeldung nicht mit dem von Ihnen geposteten Code übereinstimmt. ('char2text' gegenüber' format_char'). –

+0

@JohnZwinck Mein realer Code ist ziemlich lang und der Code hier ist etwas vereinfacht. Wenn es wie verwirrend aussieht, werde ich es bearbeiten. Type (charlist [0]) ist 'string' – PaleNeutron

Antwort

16

Das Problem ist, dass Sie eine unklinkbare Instanzvariable (namelist) in der Book Instanz haben. Da Sie pool.map für eine Instanzmethode aufrufen und Sie unter Windows arbeiten, muss die gesamte Instanz auswählbar sein, damit sie an den untergeordneten Prozess übergeben wird. Book.namelist ist ein offenes Dateiobjekt (_io.BufferedReader), das nicht gebeizt werden kann. Sie können dies auf verschiedene Arten beheben. Basierend auf dem Beispiel-Code, es sieht aus wie Sie gerade format_char eine Top-Level-Funktion machen könnte:

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 

Wenn jedoch in Wirklichkeit, Sie format_char brauchen eine Instanz Methode zu sein, können Sie __getstate__/__setstate__ verwenden Book picklable zu machen , durch das namelist Argument von der Instanz zu entfernen, bevor es Beizen:

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 

Dies wäre in Ordnung, solange Sie nicht namelist in dem untergeordneten Prozess zugreifen müssen.

+0

Danke! Es funktioniert jetzt gut und meine Vermutung ist falsch. – PaleNeutron

Verwandte Themen