multiprocessing.pool.MaybeEncodingError: 'TypeError ("не может сериализовать" _io.BufferedReader "объект",) " - PullRequest
0 голосов
/ 17 февраля 2019

Почему приведенный ниже код работает только с multiprocessing.dummy, но не с простым multiprocessing.

import urllib.request
#from multiprocessing.dummy import Pool #this works
from multiprocessing import Pool

urls = ['http://www.python.org', 'http://www.yahoo.com','http://www.scala.org', 'http://www.google.com']

if __name__ == '__main__':
    with Pool(5) as p:
        results = p.map(urllib.request.urlopen, urls)

Ошибка:

Traceback (most recent call last):
  File "urlthreads.py", line 31, in <module>
    results = p.map(urllib.request.urlopen, urls)
  File "C:\Users\patri\Anaconda3\lib\multiprocessing\pool.py", line 268, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "C:\Users\patri\Anaconda3\lib\multiprocessing\pool.py", line 657, in get
    raise self._value
multiprocessing.pool.MaybeEncodingError: Error sending result: '[<http.client.HTTPResponse object at 0x0000016AEF204198>]'. Reason: 'TypeError("cannot serialize '_io.BufferedReader' object")'

Чего не хватает, чтобы он работал без"пустышка"?

1 Ответ

0 голосов
/ 17 февраля 2019

http.client.HTTPResponse -объект, который вы получаете от urlopen(), имеет прикрепленный _io.BufferedReader -объект, и этот объект не может быть выбран.

pickle.dumps(urllib.request.urlopen('http://www.python.org').fp)
Traceback (most recent call last):
...
    pickle.dumps(urllib.request.urlopen('http://www.python.org').fp)
TypeError: cannot serialize '_io.BufferedReader' object

multiprocessing.Pool нужно будет выбрать (сериализовать) результаты, чтобы отправить их обратно в родительский процесс, и здесь это не получается.Так как dummy использует потоки вместо процессов, процесс сортировки не будет выполняться, поскольку потоки в одном и том же процессе естественным образом совместно используют свою память.

Общее решение для этого TypeError:

  1. считывание буфера и сохранение содержимого (при необходимости)
  2. удаление ссылки на '_io.BufferedReader' из объекта, который вы пытаетесь выделить

В вашем случае вызов .read() на http.client.HTTPResponse очистит и удалит буфер, поэтому функция преобразования ответа в что-то, что можно перехватить, может просто сделать это:

def read_buffer(response):
    response.text = response.read()
    return response

Пример:

r = urllib.request.urlopen('http://www.python.org')
r = read_buffer(r)
pickle.dumps(r)
# Out: b'\x80\x03chttp.client\nHTTPResponse\...

ДоВы рассматриваете этот подход, убедитесь, что вы действительно хотите использовать многопроцессорность вместо многопоточности.Для задач, связанных с вводом / выводом, как у вас здесь, многопоточность была бы достаточной, так как большую часть времени тратится на ожидание (в любом случае, времени процессора) ответа.Многопроцессорная обработка и задействованный IPC также вносят существенные накладные расходы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...