Python 协程 gevent 常规用法
·
Python gevent 常规用法
gevent 是 Python 协程(Coroutine) 库,基于 greenlet 实现,用于IO 密集型任务(爬虫、网络请求、文件读写),单线程就能并发,性能极高。
一、安装
pip install gevent
# 慢的话用国内源
pip install gevent -i https://pypi.tuna.tsinghua.edu.cn/simple
二、核心概念
- 协程:单线程内并发,切换开销极小
- gevent:自动识别 IO 阻塞,自动切换协程
- 猴子补丁(monkey patch):把 Python 默认阻塞 IO 变成非阻塞
三、最常用写法
1. 基础协程任务
# 第一步:必须先打猴子补丁(关键)
from gevent import monkey
monkey.patch_all()
import gevent
import time
def task(name):
print(f"任务 {name} 开始")
# gevent.sleep 是协程延时,会自动切换任务
# 不能用 time.sleep(会阻塞整个线程)
gevent.sleep(2)
print(f"任务 {name} 结束")
if __name__ == '__main__':
# 记录开始时间
start = time.time()
# 创建协程
g1 = gevent.spawn(task, "A")
g2 = gevent.spawn(task, "B")
g3 = gevent.spawn(task, "C")
# 等待所有协程执行完毕
gevent.joinall([g1, g2, g3])
print(f"总耗时:{time.time() - start:.2f} 秒")
运行结果
任务 A 开始
任务 B 开始
任务 C 开始
任务 A 结束
任务 B 结束
任务 C 结束
总耗时:2.01 秒
四、gevent 常用 API 大全
1. 创建协程
g = gevent.spawn(函数名, 参数1, 参数2...)
2. 等待协程
gevent.joinall([g1, g2]) # 等待列表中所有协程完成
g.join() # 等待单个协程
3. 协程延时
gevent.sleep(秒数) # 协程友好,自动切换
# ❌ 禁止用 time.sleep()(会阻塞所有协程)
4. 获取协程返回值
def func():
return "结果"
g = gevent.spawn(func)
gevent.joinall([g])
print(g.value) # 获取返回值
5. 捕获协程异常
try:
g = gevent.spawn(危险函数)
g.join()
except Exception as e:
print("出错:", e)
五、gevent 并发爬虫(最常用场景)
from gevent import monkey
monkey.patch_all()
import gevent
import requests
def fetch(url):
print(f"正在请求:{url}")
res = requests.get(url)
print(f"{url} 响应长度:{len(res.text)}")
if __name__ == '__main__':
urls = [
"https://www.baidu.com",
"https://www.qq.com",
"https://www.jd.com"
]
# 批量创建协程
tasks = [gevent.spawn(fetch, url) for url in urls]
gevent.joinall(tasks)
✅ 3 个网络请求几乎同时发出,速度极快
六、gevent 队列(生产者消费者模型)
from gevent import monkey
monkey.patch_all()
import gevent
from gevent.queue import Queue
q = Queue(maxsize=3)
def producer():
for i in range(5):
q.put(f"数据{i}")
print("生产:数据", i)
gevent.sleep(0.5)
def consumer():
while True:
data = q.get()
print("消费:", data)
gevent.sleep(1)
gevent.joinall([
gevent.spawn(producer),
gevent.spawn(consumer)
])
七、必须记住的 3 条规则(不遵守必出 BUG)
- 第一行必须打补丁
from gevent import monkey monkey.patch_all() - 不能用
time.sleep(),必须用gevent.sleep() - 只适合 IO 密集型(网络、文件、数据库),不适合 CPU 计算
八、gevent 与 线程/进程 对比
| 方式 | 开销 | 并发数 | 适用场景 |
|---|---|---|---|
| 进程 | 大 | 低 | CPU 密集 |
| 线程 | 中 | 中 | IO 密集 |
| gevent 协程 | 极小 | 极高(上万) | IO 密集(首选) |
总结
gevent是 Python 最高效的 IO 并发方案- 必须加
monkey.patch_all() - 核心 API:
spawn、joinall、sleep - 适合:爬虫、接口请求、socket 服务
更多推荐

所有评论(0)