如何检测Gevent的猴子补丁是否激活?

15 投票
4 回答
6403 浏览
提问于 2025-04-18 13:29

我有一个用Python写的单元测试,它依赖于multiprocessing,所以在Gevent的猴子补丁(monkey-patching)生效时不能运行。有没有什么Python语句可以告诉我gevent.monkey.patch_all是否已经运行过了呢?

4 个回答

0

如果你想检查一个套接字实例

def is_socket_patched(sock):
    return sock.__module__.startswith("gevent")
8

这是我用来检测gevent猴子补丁是否激活的方法。

def is_gevent_monkey_patched():
    try:
        from gevent import monkey
    except ImportError:
        return False
    else:
        return bool(monkey.saved)

正如A. Jesse Jiryu Davis提到的,这个方法只适用于gevent 1.0.x版本。

更新:在gevent 1.1版本中,有一个支持的API,可以帮助我们知道哪些对象已经被猴子补丁处理过。所以对于gevent 1.1的答案可以是:

def is_gevent_monkey_patched():
    try:
        from gevent import monkey
    except ImportError:
        return False
    else:
        return monkey.is_module_patched('__builtin__')

顺便说一下,我发现monkey.is_module_patched('sys')总是返回False。在运行monkey.patch_all()之后查看monkey.saved.keys(),我认为只有以下模块是有效的检查对象:

['_threading_local', '_gevent_saved_patch_all', 'socket', 'thread', 'ssl', 
 'signal', '__builtin__', 'subprocess', 'threading', 'time', 'os', 'select']
13

据我所知,gevent.monkey.saved 这个字典只有在某个项目被修改的时候才会更新。也就是说,当你对某个东西进行“修补”时,原来的内容会被放到这个字典里,而当你取消修补的时候,这个内容会被移除。例如:

>>> from gevent.monkey import saved
>>> 'sys' in saved
True
22

我不太确定有没有特别标准的方法,但一个简单的办法是查看一下 socket.socket 这个类:

import gevent.monkey, gevent.socket
gevent.monkey.patch_all()
import socket

if socket.socket is gevent.socket.socket:
    print "gevent monkey patch has occurred"

撰写回答