Gevent和猴子补丁

定义

在2018年看Flutent python时了解到猴子补丁,知道咋回事,但是现在通过代码更深刻认识猴子补丁。
猴子补丁:在运行时修改类或模块,而不改动源码。

例子1 没有用猴子补丁

import gevent
from gevent import socket
# from gevent import monkey; monkey.patch_socket()

urls = ['www.google.com', 'www.163.com', 'www.baidu.com']

def func(url):
    import requests
    result = requests.get('http://' + url)
    return result


jobs = [gevent.spawn(func, url) for url in urls]
gevent.joinall(jobs, timeout=2)

print([job.value for job in jobs])

结果:
线程一直阻塞,没有输出结果到终端。

例子2 用了猴子补丁

import gevent
from gevent import socket
from gevent import monkey; monkey.patch_socket()

urls = ['www.google.com', 'www.163.com', 'www.baidu.com']

def func(url):
    import requests
    result = requests.get('http://' + url)
    return result


jobs = [gevent.spawn(func, url) for url in urls]
gevent.joinall(jobs, timeout=2)

print([job.value for job in jobs])

结果显示并没有阻塞:

本质

  1. requests是个同步库,所以会发生阻塞。
  2. requests基于urllib3, urllib3基于socket,例子2用gevent的非阻塞socket(由greenlet运行的socket)代替urllib3的socket,所以不阻塞了。
  3. The primary pattern used in gevent is the Greenlet, a lightweight coroutine provided to Python as a C extension module

牛逼的地方?

当一个库的代码是纯 Python 的时候,加上 monkey patch 技法,那么这个库使用的就是 gevent.socket 了,从而不需要任何更改就能够获得 gevent 的同步代码异步执行的“超级牛力”

参考

  1. https://en.wikipedia.org/wiki/Monkey_patch
  2. http://www.gevent.org/intro.html#monkey-patching
  3. https://www.zhihu.com/question/29746887/answer/45469424
posted @ 2019-08-13 16:27  Rocin  阅读(552)  评论(0编辑  收藏  举报