【Python】整理一下关于gevent库的简要内容
首先
我在《入门Python3》中了解到了Python的gevent库,参考了官方文档等资料并学习了一些知识,我将其整理成了备忘录。
关于gevent库
gevent库采用事件驱动方式,当编写常规的命令式代码时,gevent会像魔术一样将组件转换为协程(注1)。
它像生成器一样运行,能够互相通信并持续追踪对方的位置。
gevent修改了许多Python标准对象,如socket等,以便于使用gevent的机制而不发生阻塞。
(注1.) 协程是一种中断和恢复处理的机制。
与常规函数不同的特点是,在处理过程中可以在任何时候中断,并从中断点重新开始处理。
关于事件驱动编程。
这份资料非常清晰易懂,我从中得到了很多参考。
使用Apache Kafka on Heroku设计和实施事件驱动架构
gevent是什么?
gevent是一个基于协程的Python网络编程库。
在本文中,我们将通过检查示例代码来加深我们对gevent以下功能的理解。
-
- グリーンレットに基づく軽量の実行ユニット
- サードパーティのモジュールに対してモンキーパッチを適応
示例代码
绿色小生菜的功能
import gevent
from gevent import socket
if __name__ == "__main__":
hosts = ['www.google.com','www.yahoo.co.jp','www.qiita.com']
jobs = [gevent.spawn(gevent.socket.gethostbyname,host) for host in hosts]
gevent.joinall(jobs,timeout=5)
# ホスト名のIPアドレスを出力
for job in jobs:
print(job.value)
$ python gevent_test.py
216.58.197.196
182.22.25.252
52.196.217.245
解释
socket模块的gethostbyname()函数用于返回与域名对应的IP地址。由于是同步的,当尝试解析地址时,它会等待并竞争抓取世界各地的命名服务器。但是,如果使用gevent版本,可以异步执行并独立地解析多个网站。
gevent.spawn()函数用于创建协程(也称为greenlet、微线程),以执行每个gevent.socket.gethostbyname(url)的操作。
与普通线程的区别在于,协程不会阻塞。阻塞处理是指其他线程无法访问资源的处理方式,也称为互斥处理或互斥控制。即使出现会导致普通线程阻塞的情况,gevent也会切换到其他协程来进行控制。
gevent.joinall()方法会等待所有派生出来的任务都结束。
gevent库中的Monkey Patch功能
可以使用Monkey Patching函数来替代gevent版本的socket。
这些函数会修改标准模块,如socket,而不是调用gevent版本的模块来使用greenlet。
这在Python代码上可以正常工作,但不适用于使用C编写的库。
关于Monkey Patching
-
- 元のコードを変更することなく、動的にコードを拡張/変更する事の総称のこと.(メタプログラミングの一種)
-
- ライブラリのコードを直接変えたくない時とかに利用される
- テスト系ライブラリでよく利用される
import gevent
from gevent import monkey;monkey.patch_all()
import socket
import time
if __name__ == "__main__":
hosts = ['www.google.com','www.yahoo.co.jp','www.qiita.com']
#gevent.spawn()の引数にはsocket.gethostbynameを指定しているが,ここがモンキーパッチング対象
jobs = [gevent.spawn(socket.gethostbyname,host) for host in hosts]
gevent.joinall(jobs,timeout=5)
gevent.spawn()
for job in jobs:
print(job.value)
解释
在genvent_test.py中,明确导入了gevent.socket模块。
另一方面,在gevent_monkey.py中,明确导入了标准库的socket模块。如果不使用monkey.patch_all()函数,在导入socket模块的阶段,导入的将是标准库的socket模块,而不是gevent版的socket模块。
通过使用monkey.patch_all()函数(示例代码中使用的是monkey.patch_all()),可以将标准库替换为gevent版的socket模块。
感受
这里所描述的内容完全不实际,而且我想进一步调查。
计划添加我通过调查得到的信息。
文献引用
-
- 入門Python3
- http://www.gevent.org/