python3 协程gevent模块(遇到IO自动切换)
协程
在一个线程中并发执行多个任务,当遇到IO操作的时候,自动切换到其他任务去执行。
gevent 是第三方的一个模块,需要手动安装pip install gevent
先看一个例子
from gevent import monkey monkey.patch_all() # 记住一定放在第一行,这里是打补丁的意思,time模块在使用协程gevent模块的时候,必须打补丁才行,记得放在第一行。 import gevent import time def eat(name): print(f"{name} eat first") time.sleep(3) print(f"{name} eat second") def play(name): print(f"{name} play phone 1") time.sleep(2) print(f"{name} play phone 2") g1 = gevent.spawn(eat, "lily") g2 = gevent.spawn(play, name="lily") g1.join() g2.join()
执行结果:
lily eat first lily play phone 1 lily play phone 2 lily eat second
协程之间数据是安全的,因为同一时间只能有一个协程在执行。
接下来看下协程能干什么?先看一个正常爬取多个网页源代码的例子(爬取网页)
import time import requests def get_page(url): response = requests.get(url) print(url) if response.status_code == 200: print(response.text) start_time = time.time() get_page("https://www.python.org") get_page("https://www.yahoo.com") get_page("https://github.com") print("执行时间:%s" % (time.time()-start_time))
执行结果:
执行时间:4.218241214752197
再看一个使用了协程后的时间(使用gevent模块爬取网页)
from gevent import monkey;monkey.patch_all() import gevent import time import requests def get_page(url): response = requests.get(url) print(url) if response.status_code == 200: print(response.text) start_time = time.time() g1 = gevent.spawn(get_page, "https://www.python.org") g2 = gevent.spawn(get_page, "https://www.yahoo.com") g3 = gevent.spawn(get_page, "https://github.com") gevent.joinall([g1, g2, g3]) print("执行时间:%s" % (time.time()-start_time))
执行结果:
执行时间:2.399137496948242
明显比上面不使用协程的程序快多了。