Python多处理:增加池大小后的管道断开异常

时间:2017-07-21 06:33:41

标签: python python-multiprocessing

我得到的例外。我所做的就是增加了游泳池数量

代码

 def parse(url):
  r = request.get(url)
POOL_COUNT = 75
with Pool(POOL_COUNT) as p:
    result = p.map(parse, links)



File "/usr/lib64/python3.5/multiprocessing/pool.py", line 130, in worker
    put((job, i, (False, wrapped)))
  File "/usr/lib64/python3.5/multiprocessing/queues.py", line 355, in put
    self._writer.send_bytes(obj)
  File "/usr/lib64/python3.5/multiprocessing/connection.py", line 200, in send_bytes
    self._send_bytes(m[offset:offset + size])
  File "/usr/lib64/python3.5/multiprocessing/connection.py", line 404, in _send_bytes
    self._send(header + buf)
  File "/usr/lib64/python3.5/multiprocessing/connection.py", line 368, in _send
    n = write(self._handle, buf)
BrokenPipeError: [Errno 32] Broken pipe
Process ForkPoolWorker-26:
Traceback (most recent call last):
  File "/usr/lib64/python3.5/multiprocessing/pool.py", line 125, in worker
    put((job, i, result))
  File "/usr/lib64/python3.5/multiprocessing/queues.py", line 355, in put
    self._writer.send_bytes(obj)
  File "/usr/lib64/python3.5/multiprocessing/connection.py", line 200, in send_bytes
    self._send_bytes(m[offset:offset + size])
  File "/usr/lib64/python3.5/multiprocessing/connection.py", line 404, in _send_bytes
    self._send(header + buf)
  File "/usr/lib64/python3.5/multiprocessing/connection.py", line 368, in _send
    n = write(self._handle, buf)
BrokenPipeError: [Errno 32] Broken pipe

3 个答案:

答案 0 :(得分:0)

这个简单版本的代码在这里可以使用任意数量的POOL_COUNT

from multiprocessing import Pool
def parse(url):
  r = url
  print(r)

POOL_COUNT = 90
with Pool(processes=POOL_COUNT) as p:
    links = [str(i) for i in range(POOL_COUNT)]
    result = p.map(parse, links)

不是吗? 所以问题应该在request部分,可能需要sleep

答案 1 :(得分:0)

我也看到了断管异常。但我的事情更复杂。

单独增加池大小会导致异常的一个原因是你在请求模块中获得了太多东西,因此它可能导致内存不足。然后它就会出现故障,特别是你有一个小的交换。

Edit1:我认为这是由内存使用造成的。太多的池连接占用了太多的内存,最终破坏了。调试非常困难,我自己将池大小限制为4,因为我有一个小RAM和大包。

答案 2 :(得分:0)

我尝试使用以下脚本在AWS t2.small实例(如您所述的2GB RAM)上重现(请注意,您在请求中错过了s s .get() ,假设您正在使用gsutil -m acl ch -r -u -compute@developer.gserviceaccount.com:R gs://foo-bucket,并且return也缺失了):

from multiprocessing import Pool
import requests
def parse(url):
  a = requests.get(url)
  if a.status_code != 200:
    print(a)
  return a.text
POOL_COUNT = 120
links = ['http://example.org/' for i in range(1000)]
with Pool(POOL_COUNT) as p:
  result = p.map(parse, links)
print(result)
可悲的是,我没有像你那样遇到同样的问题。

从您发布的堆栈跟踪中,问题似乎是启动parse函数,而不是在请求模块本身。看起来主进程无法将数据发送到其中一个已启动的进程。

无论如何:这个操作不受CPU限制,瓶颈是网络(很可能是远程服务器最大连接,或者也可能是),你使用多线程要好得多。这很可能也更快,因为multiprocessing.map需要在进程之间进行通信,这意味着需要对parse的返回进行pickle,然后将其发送到主进程。

要尝试使用线程而不是进程,只需执行from multiprocessing.pool import ThreadPool并将Pool替换为代码中的ThreadPool