網絡異步請求之gevent

咱們知道對於網絡請求這種IO bound的場景來講,最怕的就是某個請求阻塞了其他的操做,讓併發性大大下降。今天就來介紹一款python下的併發庫-geventpython

首先看一下他本身的介紹:bash

gevent是一個基於libev的併發庫。它爲各類併發和網絡相關的任務提供了整潔的API。網絡

嗯,確實很簡潔,很易使用。待會咱們就見識到了。併發

同步IO

首先咱們來看看傳統的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

咱們再來寫一個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的更多用法請參考其官方文檔。這麼簡單又好用的庫趕忙試試吧。^_^

相關文章
相關標籤/搜索