咱們知道對於網絡請求這種IO bound的場景來講,最怕的就是某個請求阻塞了其他的操做,讓併發性大大下降。今天就來介紹一款python下的併發庫-gevent。python
首先看一下他本身的介紹:bash
gevent是一個基於libev的併發庫。它爲各類併發和網絡相關的任務提供了整潔的API。網絡
嗯,確實很簡潔,很易使用。待會咱們就見識到了。併發
首先咱們來看看傳統的IO請求。
好比咱們請求:http://httpbin.org/ip 發個http get請求會獲得咱們的ip地址,如:異步
{ "origin": "183.240.202.14" }
咱們來寫個腳本連續發50個get請求到這個地址,以模擬多個請求。(腳本命名爲get.py)socket
import requests url = 'http://httpbin.org/ip' for i in range(50): print("{}: {}".format(i, requests.get(url).text))
統計一下運行時間:url
$ time python3 get.py (輸出略...) python3 get.py 0.56s user 0.06s system 1% cpu 35.606 total
大概花費35s鍾,固然不一樣網絡環境可能結果不一樣。並且打印出來的結果是按照1, 2, 3...50這樣的順序來的,說明整個請求是同步的,一個請求結束再發下一個請求。spa
咱們再來寫一個gevent版的get.py,命名爲gevent_get.pycode
import requests import gevent import gevent.monkey # 這裏將socket變成異步 gevent.monkey.patch_socket() url = 'http://httpbin.org/ip' def hello(i): print("{}: {}".format(i, requests.get(url).text)) tasks = [gevent.spawn(hello, i) for i in range(50)] gevent.joinall(tasks)
再來看看運行時間:orm
$ time python3 gevent_get.py (輸出略...) python3 gevent_get.py 0.49s user 0.06s system 39% cpu 1.403 total
個人天!才1.4秒左右,並且打印出來的結果沒有按照1, 2, 3...50這樣排列,而是按照隨機順序排列的,說明整個請求是異步非阻塞的。
我又多試了幾回,gevent的效率確實牛,遠遠高於同步io請求。最近在個人一個爬蟲小項目裏面用進程池 + gevent,爬取80個頁面,大概花費40s左右,每一個頁面只要0.5s,並且還包括DOM解析的時間,而用同步請求則花費大概300s左右。
gevent的更多用法請參考其官方文檔。這麼簡單又好用的庫趕忙試試吧。^_^