multiprocessing.Pool:如果未使用虚拟模块,则为urllib TypeError

时间:2019-02-17 19:14:15

标签: python multiprocessing urllib python-multiprocessing python-multithreading

为什么下面的代码仅适用于“ 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 :(得分:1)

响应对象附加了一个BufferReader对象,因此无法腌制该对象。

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使用线程而不是进程,因此不会出现酸洗,因为同一进程中的线程自然共享其内存。

您的示例并未显示出无论如何都需要在多线程上使用多处理。对于像此处这样的I / O绑定任务,线程化就足够了,因为大部分时间都花在等待响应上。如果您还有其他使用多重处理的原因,一种选择是采用这种包装函数对响应对象进行后处理,即在将结果发送回父对象之前,该结果不再包含BufferReader。