7

Tôi đang dò tìm để sử dụng multiprocessing trong mã của mình để có hiệu suất tốt hơn.Tôi có thể sử dụng multiprocessing.Pool trong một phương thức của một lớp học không?

Tuy nhiên, tôi đã nhận ra lỗi như sau:

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 

Tôi đã thử nó một cách khác và đã nhận lỗi này:

TypeError: cannot serialize '_io.TextIOWrapper' object 

Mã của tôi trông như thế này:

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) 

Tôi nghĩ rằng lỗi được nâng lên vì không sử dụng Pool trong chức năng chính.

Giả sử của tôi có đúng không? Và làm cách nào tôi có thể sửa đổi mã của mình để sửa lỗi?

+0

'Loại (charlist [0])' nói gì? Và có một chút khó hiểu vì thông báo lỗi của bạn không khớp với mã bạn đã đăng. ('char2text' và' format_char'). –

+0

@JohnZwinck Mã thực sự của tôi khá dài và mã ở đây là một cái gì đó được đơn giản hóa. Nếu có vẻ khó hiểu, tôi sẽ chỉnh sửa nó.type (charlist [0]) là 'string' – PaleNeutron

Trả lời

16

Vấn đề là bạn đã có một biến mẫu không thể nhấp (namelist) trong ví dụ Book. Bởi vì bạn đang gọi pool.map trên một phương thức thể hiện và bạn đang chạy trên Windows, toàn bộ cá thể cần phải được chọn để nó được chuyển cho tiến trình con. Book.namelist là đối tượng tệp mở (_io.BufferedReader), không thể được chọn. Bạn có thể sửa lỗi này bằng một vài cách. Dựa trên mã ví dụ, có vẻ như bạn chỉ có thể làm cho format_char một chức năng cấp cao nhất:

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 

Tuy nhiên, nếu trong thực tế, bạn cần format_char là một phương pháp dụ, bạn có thể sử dụng __getstate__/__setstate__ để làm Book picklable , bằng cách loại bỏ các namelist lập luận từ các ví dụ trước khi tẩy nó:

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 

Đây sẽ là ok miễn là bạn không cần phải truy cập vào namelist trong quá trình đứa trẻ.

+0

Cảm ơn! Nó hoạt động tốt ngay bây giờ, và phỏng đoán của tôi là sai. – PaleNeutron

Các vấn đề liên quan