日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python模块介绍-gevent介绍:基于协程的网络库

發布時間:2023/12/20 python 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python模块介绍-gevent介绍:基于协程的网络库 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

python模塊介紹-gevent介紹:基于協程的網絡庫 ? ?

介紹

gevent是基于協程的Python網絡庫。特點:

  • 基于libev的快速事件循環(Linux上epoll,FreeBSD上kqueue)。

  • 基于greenlet的輕量級執行單元。

  • API的概念和Python標準庫一致(如事件,隊列)。

  • 可以配合socket,ssl模塊使用。

  • 能夠使用標準庫和第三方模塊創建標準的阻塞套接字(gevent.monkey)。

  • 默認通過線程池進行DNS查詢,也可通過c-are(通過GEVENT_RESOLVER=ares環境變量開啟)。

  • TCP/UDP/HTTP服務器

  • 子進程支持(通過gevent.subprocess)

  • 線程池

安裝

gevent目前支持python2.5-2.7,python2.6以前的版本如果要使用ssl還需要安裝ssl模塊。

#?pip?install?gevent

實例

下面的示例展示了如何同時運行任務。

>>>?import?gevent>>>?from?gevent?import?socket>>>?urls?=?['www.google.com',?'www.example.com',?'www.python.org']>>>?jobs?=?[gevent.spawn(socket.gethostbyname,?url)?for?url?in?urls]>>>?gevent.joinall(jobs,?timeout=2)>>>?[job.value?for?job?in?jobs]['74.125.128.106',?'93.184.216.119',?'82.94.164.162']

job發起之后,gevent.joinall()等待完成,不超過2秒。結果收集在gevent.Greenlet.value屬性。 gevent.socket.gethostbyname()和socket.gethostbyname()的接口一樣,但它并不阻塞解釋器,其他 greenlet繼續暢通無阻的處理請求。

靈猴補丁(Monkey patching)

上面例子使gevent.socket進行socket操作。如果使用標準socket模塊將有3倍耗時,因為DNS請求是串行的。在greenlet中使用標準socket模塊毫無意義,這些模塊和包是怎么建立在socket之上的?

monkey patching這時起作用了,gevent.monkey小心地使用兼容副本替換標準socket模塊的函數和類。這樣,即使是不知道gevent的模塊也受益于greenlet環境運行。

>>>?from?gevent?import?monkey;?monkey.patch_socket()>>>?import?urllib2?#?it's?usable?from?multiple?greenlets?now

下面是使用urllib2進行下載的實例:

#!/usr/bin/env?python#?-*-?coding:?utf-8?-*-#?Copyright?(c)?2009?Denis?Bilenko.?See?LICENSE?for?details."""Spawn?multiple?workers?and?wait?for?them?to?complete"""urls?=?['http://www.google.com',?'http://www.yandex.ru',?'http://www.python.org']import?geventfrom?gevent?import?monkey#?patches?stdlib?(including?socket?and?ssl?modules)?to?cooperate?with?other?greenletsmonkey.patch_all()import?urllib2def?print_head(url):print('Starting?%s'?%?url)data?=?urllib2.urlopen(url).read()print('%s:?%s?bytes:?%r'?%?(url,?len(data),?data[:50]))jobs?=?[gevent.spawn(print_head,?url)?for?url?in?urls]gevent.wait(jobs)

執行結果:

#?./test.py? Starting?http://www.google.com Starting?http://www.yandex.ru Starting?http://www.python.org http://www.google.com:?11246?bytes:?'<!doctype?html><html?itemscope=""?itemtype="http:/'http://www.python.org:?20471?bytes:?'<!DOCTYPE?html?PUBLIC?"-//W3C//DTD?XHTML?1.0?Trans'http://www.yandex.ru:?208804?bytes:?'<!DOCTYPE?html><html?class="i-ua_js_no?i-ua_css_st'

事件循環

不像其他網絡庫,gevent和eventlet類似, 在一個greenlet中隱式開始事件循環。沒有必須調用run()或dispatch()的反應器(reactor),在twisted中是有 reactor的。當gevent的API函數想阻塞時,它獲得Hub實例(執行時間循環的greenlet),并切換過去。如果沒有集線器實例則會動態 創建。

libev提供的事件循環默認使用系統最快輪詢機制,設置LIBEV_FLAGS環境變量可指定輪詢機制。LIBEV_FLAGS=1為select, LIBEV_FLAGS = 2為poll, LIBEV_FLAGS = 4為epoll,LIBEV_FLAGS = 8為kqueue。請閱讀libev文檔了解更多信息http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#FUNCTIONS_CONTROLLING_EVENT_LOOPS。

Libev的API位于gevent.core下。注意libev API的回調在Hub的greenlet運行,因此使用同步greenlet的API??梢允褂胹pawn()和Event.set()等異步API。

多任務合作

所有greenlets都在同一個操作系統線程調度執行。直到特定的greenlet放棄控制,(調用阻塞函數切換到Hub),其他greenlet才有 機會運行。對于I / O密集型應用程序這通常不是問題,但做CPU密集型或者調用封鎖繞過libev事件循環的I/0功能的時會有問題。

一般不需要在greenlet之間同步訪問共享對象, 所以Lock和Semaphore類盡管存在,但是很少使用。從線程和多處理等其他概念仍然常用,如下:

  • Event:喚醒在調用Event.wait()方法的greenlets。

  • AsyncResult:和Event類似,但允許傳遞值或異常。隊列和JoinableQueue。

  • Queu和JoinableQueue.

輕量級偽線程

greenlet通過創建greenlet實例并調用其start方法發起。(spawn()函數就是做這個的快捷方式)。 start方法給greenlet安排一個開關,當前greenlet放棄控制觸發。如果有多個active的事件,將不確定的順序一一執行。

如果在執行過程中出現錯誤,將無法離開greenlet的邊界。未處理的錯誤導致打印堆棧跟蹤及失敗函數和參數:

>>>?gevent.spawn(lambda?:?1/0)>>>?gevent.sleep(1)Traceback?(most?recent?call?last):...ZeroDivisionError:?integer?division?or?modulo?by?zero<Greenlet?at?0x7f2ec3a4e490:?<function?<lambda...>>?failed?with?ZeroDivisionError

traceback在greenlet退出時同步打印至sys.stderr。

Greenlet實例有如下有用的方法:

  • join – waits until the greenlet exits;

  • kill – interrupts greenlet’s execution;

  • get – returns the value returned by greenlet or re-raised the exception that killed it.

繼承Greenlet類重載其str可以自定義traceback后的字符串。另外還需要重載_run()方法以及在init中調用Greenlet.init(self)。

class?MyNoopGreenlet(Greenlet):def?__init__(self,?seconds):Greenlet.__init__(self)self.seconds?=?seconds????def?_run(self):gevent.sleep(self.seconds)def?__str__(self):return?'MyNoopGreenlet(%s)'?%?self.seconds

可以異步結束Greenlet,浙江將恢復等待的greenlet,不繼續執行而是引發GreenletExit。

>>>?g?=?MyNoopGreenlet(4)>>>?g.start()>>>?g.kill()>>>?g.deadTrue

GreenletExit及其子類的處理方式不同于其他異常。GreenletExit不被視為異常狀態,不打印traceback。get可以獲得GreenletExit是GET,就好像它是由greenlet返回,不是raise。

kill方法可以自定義的異常:

>>>?g?=?MyNoopGreenlet.spawn(5)?#?spawn()?creates?a?Greenlet?and?starts?it>>>?g.kill(Exception("A?time?to?kill"))Traceback?(most?recent?call?last):...Exception:?A?time?to?kill MyNoopGreenlet(5)?failed?with?Exception

kill還可以接受timeout參數指定greenlet退的等待秒數。注意,kill不能保證目標greenlet不會忽視該異常,因此給kill傳遞timeout是個好方法。

超時

gevent的API中的許多函數是同步的,阻塞當前greenlet直到操作完成。例如,kill會等到greenlet結束。多數可以傳遞參數block=False異步執行。

此外,許多同步函數接受超時參數,指定可以阻塞多久(比如:Event.wait(), Greenlet.join(), Greenlet.kill(), AsyncResult?.get()等)。

socket和SSLObject實例也可以超時,由setTimeout方法設置。

如果這些還不夠用,Timeout類可以給任意(yielding)代碼塊增加超時。

了解更多

限制并發可以使用Pool類(參見實例: dns_mass_resolve.py)

gevent自帶的TCP/SSL/HTTP/WSGI服務器。參見實現服務器部分http://www.gevent.org/servers.html。

外部資源

gevent For the Working Python Developer: 是一個更全面的教程。http://sdiehl.github.io/gevent-tutorial/. 中文版本參見http://xlambda.com/gevent-tutorial/


參考資料

  • gevent主頁: http://www.gevent.org/

  • gevent英文文檔: http://www.gevent.org/intro.html

  • gevent程序員指南: http://xlambda.com/gevent-tutorial/

  • 下載地址:https://pypi.python.org/pypi/gevent

  • 作者博客:http://my.oschina.net/u/1433482

  • Linux slab 分配器剖析

  • 類型:翻譯


轉載于:https://my.oschina.net/u/1433482/blog/192562

總結

以上是生活随笔為你收集整理的python模块介绍-gevent介绍:基于协程的网络库的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。