为什么下面的代码仅适用于“ 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")'
缺少什么,这样就可以在没有“虚拟”的情况下工作?
答案 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。>