Gevent monkeypatching打破多处理

时间:2011-12-30 10:04:42

标签: python multiprocessing gevent

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

以下是代码的简化片段:

import multiprocessing

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

manager = multiprocessing.Manager()
q = manager.Queue()

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

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

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

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

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

>>> gevent.version_info
(1, 0, 0, 'alpha', 3)

有什么想法吗?

5 个答案:

答案 0 :(得分:17)

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

我在类似的情况下遇到了同样的问题,并将其跟踪到gevent/monkey.py函数patch_socket()_socket.socket = socket.socket的第115行。socket。评论这条线可以防止破损。

这是gevent用自己的库替换stdlib multiprocessing.connection库的地方。 socket广泛使用gevent.monkey.patch_all()库,显然不能容忍这种变化。

具体而言,您将在导入的模块执行socket=False调用而未设置grequests的任何情况下看到此信息。在我的情况下,{{1}}执行了此操作,我不得不重写套接字模块的修补以修复此错误。

答案 1 :(得分:9)

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

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

答案 2 :(得分:2)

如果您将使用原始队列,那么即使使用猴子修补套接字,您的代码也能正常工作。

import multiprocessing

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

q= multiprocessing.Queue()

答案 3 :(得分:1)

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

修改

删除了之前的回答,因为我在Ubuntu 11.10 VPS上尝试了你的代码,而且我遇到了同样的错误。

看起来像Eventlet have this issue too

答案 4 :(得分:1)

写了一个替代的Nose Multiprocess插件 - 这个插件应该适用于各种基于Gevent的疯狂修补。

https://pypi.python.org/pypi/nose-gevented-multiprocess/

https://github.com/dvdotsenko/nose_gevent_multiprocess

  • 为工作进程从multiprocess.fork切换到普通subprocess.popen(修复模块级错误的共享对象问题)
  • 从multiprocess.Queue切换到JSON-RPC over HTTP for master-to-clients RPC
  • 现在理论上可以将测试分发到多台机器