定义
在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])
结果显示并没有阻塞:
本质
- requests是个同步库,所以会发生阻塞。
- requests基于urllib3, urllib3基于socket,例子2用gevent的非阻塞socket(由greenlet运行的socket)代替urllib3的socket,所以不阻塞了。
- The primary pattern used in gevent is the Greenlet, a lightweight coroutine provided to Python as a C extension module