gevent的monkey.patch_all()失败主因是未在所有import前执行,导致requests、psycopg2等库已初始化原生阻塞IO,协程无法接管;必须置于入口文件首行,并配合gevent兼容驱动与连接池配置。

为什么直接 monkey_patch 会失败
gevent 的 monkey.patch_all() 看似一键协程化,但实际常在导入第三方库后调用就失效——因为某些库(比如 requests、psycopg2)在模块顶层就完成了 socket 初始化或线程绑定,patch 必须在任何相关模块 import 之前执行。一旦 import requests 先于 gevent.monkey.patch_all(),后续的 HTTP 请求仍走原生阻塞 socket。
实操建议:
- 把
gevent.monkey.patch_all()放在项目入口文件(如main.py)最顶部,且确保它出现在所有其他 import 之前 - 若使用 Flask/Django 等框架,需在 WSGI 入口(如
wsgi.py)中 patch,而非视图文件里 - 验证是否生效:运行后检查
socket.socket是否已替换为gevent._socket3.socket,可打印socket.socket.__module__
同步数据库调用怎么不卡住整个协程池
PostgreSQL 的 psycopg2 和 MySQL 的 pymysql 默认都是阻塞 I/O,即使打了 monkey patch,如果连接未设为非阻塞模式,gevent 仍无法调度其他协程。关键不是“有没有 patch”,而是“连接是否启用 gevent 兼容模式”。
实操建议:
- 对
psycopg2:必须使用psycopg2.gevent子模块,并显式调用psycopg2.gevent.register_psycopg2();或者改用psycopg2cffi+gevent补丁 - 对
pymysql:确保使用pymysql.connections.Connection时传入autocommit=True,并设置read_timeout/write_timeout避免无限等待 - 更稳妥的做法是改用原生支持异步的驱动,如
asyncpg(需配合asyncio)或aiomysql;若必须留 gevent,则用连接池封装,例如gevent.pool.Pool控制并发数,避免耗尽 hub
time.sleep() 和 threading.Lock 怎么安全替换
遗留代码里大量 time.sleep(1) 或 threading.Lock 在 gevent 下会退化为全局阻塞——因为原生 time.sleep 不 yield,而 threading.Lock 底层依赖操作系统线程互斥,gevent 无法接管。
实操建议:
- 全局搜索替换:
time.sleep→gevent.sleep;注意gevent.sleep(0)是强制让出控制权的常用技巧 -
threading.Lock→gevent.lock.Semaphore(单次 acquire)或gevent.lock.RLock(可重入);不要混用,否则死锁 - 警惕日志模块:
logging.FileHandler写磁盘是阻塞的,高并发下应改用gevent.queue.Queue做异步日志缓冲,或切到concurrent_log_handler
如何识别哪些函数其实根本不能协程化
gevent 只能协程化「系统调用级阻塞」(如 socket、file read、sleep),对 CPU 密集型操作(如大数组排序、正则回溯、JSON 解析)完全无效。强行跑在 gevent hub 里,只会让整个事件循环卡住,表现和单线程无异。
实操建议:
- 用
gevent.hub.wait+gevent.threadpool.ThreadPool将 CPU 密集任务扔出 hub:例如pool.spawn(cpu_bound_func, *args) - 检查 C 扩展模块:像
numpy、lxml、cryptography中的底层计算通常绕过 Python GIL 但也不走 gevent hook,需单独评估 - 最易被忽略的是信号处理:gevent 默认禁用部分信号(如
SIGCHLD),若遗留代码依赖subprocess+ 信号回收子进程,需手动调用gevent.signal注册 handler
真正难的不是加几行 patch,而是厘清每个阻塞点的根源类型——IO?CPU?C 扩展?信号?锁粒度?改错一个地方,可能暴露下一个隐藏阻塞源。上线前务必用 gevent.hub.wait 配合超时做端到端压测,而不是只看 CPU 是否空转。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











