Gevent monkeypatching打破多处理

use*_*375 23 python multiprocessing gevent

我试图使用多处理池来运行一组进程,每个进程都运行一个gelet池.原因是有很多网络活动,但也有很多CPU活动,所以为了最大化我的带宽和我所有的CPU核心,我需要多个进程和gevent的异步猴子补丁.我正在使用多处理管理器来创建一个队列,进程将访问该队列以获取要处理的数据.

这是代码的简化片段:

import multiprocessing

from gevent import monkey
monkey.patch_all(thread=False)

manager = multiprocessing.Manager()
q = manager.Queue()
Run Code Online (Sandbox Code Playgroud)

以下是它产生的例外情况:

Traceback (most recent call last):
  File "multimonkeytest.py", line 7, in <module>
    q = manager.Queue()
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 667, in temp
    token, exp = self._create(typeid, *args, **kwds)
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 565, in _create
    conn = self._Client(self._address, authkey=self._authkey)
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 175, in Client
    answer_challenge(c, authkey)
  File "/usr/local/Cellar/python/2.7.2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 409, in answer_challenge
    message = connection.recv_bytes(256)         # reject large message
 IOError: [Errno 35] Resource temporarily unavailable
Run Code Online (Sandbox Code Playgroud)

我相信这一定是由于普通套接字模块和gevent套接字模块的行为有所不同.

如果我在子进程中monkeypatch,则成功创建队列,但是当子进程尝试从队列中获取get()时,会发生非常类似的异常.由于在子进程中执行大量网络请求,因此套接字需要进行monkeypatched.

我的gevent版本,我认为是最新版本:

>>> gevent.version_info
(1, 0, 0, 'alpha', 3)
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Nis*_*n.H 17

使用 monkey.patch_all(thread=False, socket=False)

我在类似的情况下遇到了同样的问题,并gevent/monkey.pypatch_socket()功能下跟踪到了第115行:_socket.socket = socket.socket.评论这条线可以防止破损.

这是gevent socket用它自己替换stdlib 库的地方.非常广泛地multiprocessing.connection使用该socket库,并且显然不能容忍这种变化.

具体来说,您将在导入的模块执行gevent.monkey.patch_all()调用而不进行设置的任何情况下看到此情况socket=False.在我的情况下,它是grequests这样做的,我不得不重写套接字模块的修补程序来修复此错误.


Jan*_*cke 9

遗憾的是,已知多处理在gevent环境中的应用会引发问题.但是,你的理由是合理的("很多网络活动,但也有很多CPU活动").如果您愿意,请查看http://gehrcke.de/gipc.这主要是为您的用例而设计的.使用gipc,您可以轻松地生成一些完全支持gevent的子进程,并让它们通过管道相互协作和/或与父进程通信.

如果您有具体问题,欢迎您回复我.

  • 我个人认为这是一个没有思想的猴子补丁,这是有问题的.任何使用gevent的东西都应该有一个非常大的警告标志,告诉它什么会破坏.尚未遇到gevent-multiprocessing不兼容性这一特定怪癖的普通程序员会(理所当然地)认为gevent不会破坏stdlib功能.在修补套接字时,gevent不会修补IPC功能(这是可行的)并不是很明显. (4认同)

rec*_*dev 1

您提供的代码在 Windows 7 上适用于我。

编辑:

删除了之前的答案,因为我已经在 Ubuntu 11.10 VPS 上尝试过你的代码,并且遇到了相同的错误。

貌似Eventlet也有这个问题