最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python協(xié)程操作之gevent(yield阻塞,greenlet),協(xié)程實(shí)現(xiàn)多任務(wù)(有規(guī)律的交替協(xié)作執(zhí)行)用法詳解

 更新時(shí)間:2019年10月14日 11:16:34   作者:houyanhua1  
這篇文章主要介紹了Python協(xié)程操作之gevent(yield阻塞,greenlet),協(xié)程實(shí)現(xiàn)多任務(wù)(有規(guī)律的交替協(xié)作執(zhí)行)用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了協(xié)程的功能、原理及gevent、greenlet實(shí)現(xiàn)協(xié)程,以及協(xié)程實(shí)現(xiàn)多任務(wù)相關(guān)操作技巧,需要的朋友可以參考下

本文實(shí)例講述了Python 協(xié)程操作之gevent(yield阻塞,greenlet),協(xié)程實(shí)現(xiàn)多任務(wù)(有規(guī)律的交替協(xié)作執(zhí)行)用法。分享給大家供大家參考,具體如下:

實(shí)現(xiàn)多任務(wù):進(jìn)程消耗的資源最大,線程消耗的資源次之,協(xié)程消耗的資源最少(單線程)。

gevent實(shí)現(xiàn)協(xié)程,gevent是通過(guò)阻塞代碼(例如網(wǎng)絡(luò)延遲等)來(lái)自動(dòng)切換要執(zhí)行的任務(wù),所以在進(jìn)行IO密集型程序時(shí)(例如爬蟲(chóng)),使用gevent可以提高效率(有效利用網(wǎng)絡(luò)延遲的時(shí)間去執(zhí)行其他任務(wù))。

GIL(全局解釋器鎖)是C語(yǔ)言版本的Python解釋器中專有的,GIL的存在讓多線程的效率變低(哪個(gè)線程搶到鎖,就執(zhí)行哪個(gè)線程)。在IO密集型程序中,多線程依然比單線程效率高(GIL通過(guò)IO阻塞自動(dòng)切換多線程)。

解決GIL(全局解釋器鎖)的問(wèn)題的三種方法:1、不要用C語(yǔ)言版本的Python解釋器。2、讓子線程運(yùn)行其他語(yǔ)言代碼(例如:主線程運(yùn)行Python代碼,子線程運(yùn)行C語(yǔ)言代碼(C語(yǔ)言的動(dòng)態(tài)庫(kù)))。3、多進(jìn)程代替多線程(多進(jìn)程可以利用多核CPU)。

demo.py(協(xié)程底層原理,yield):

import time
# 帶yield的函數(shù)并不是函數(shù),而是一個(gè)生成器模板,返回一個(gè)生成器(可用于遍歷迭代)
def task_1():
  while True:
    time.sleep(0.1)
    yield # 阻塞,等待next迭代解阻塞
def task_2():
  while True:
    time.sleep(0.1)
    yield
def main():
  t1 = task_1() # 返回的t1是一個(gè)生成器。 此時(shí)并未執(zhí)行task_1中的代碼
  t2 = task_2()
  # 先讓t1運(yùn)行一會(huì),當(dāng)t1中遇到y(tǒng)ield的時(shí)候,再返回到24行,然后
  # 執(zhí)行t2,當(dāng)它遇到y(tǒng)ield的時(shí)候,再次切換到t1中
  # 這樣t1/t2/t1/t2的交替運(yùn)行,最終實(shí)現(xiàn)了多任務(wù)....協(xié)程
  while True:
    next(t1) # 執(zhí)行task_1中的代碼,遇到y(tǒng)ield阻塞task_1。 等待下一次next激活。
    next(t2) # 實(shí)現(xiàn)task_1與task_2交替執(zhí)行,實(shí)現(xiàn)多任務(wù)...協(xié)程
if __name__ == "__main__":
  main()

demo.py(greenlet實(shí)現(xiàn)協(xié)程,封裝了yield):

from greenlet import greenlet # 需要安裝greenlet模塊 sudo pip3 install greenlet (python2.x使用pip) 
import time
def test1():
  while True:
    print("---A--")
    gr2.switch()  # 切換到gr2中的任務(wù)。
    time.sleep(0.5)
def test2():
  while True:
    print("---B--")
    gr1.switch()  # 切換到gr1中的任務(wù)。
    time.sleep(0.5)
gr1 = greenlet(test1) # greenlet 底層封裝了yield。
gr2 = greenlet(test2)
#切換到gr1中運(yùn)行
gr1.switch()

demo.py(gevent實(shí)現(xiàn)協(xié)程,封裝了greenlet,遇到阻塞代碼自動(dòng)切換協(xié)程任務(wù)):

import gevent # 需要安裝gevent模塊 sudo pip3 install gevent (python2.x使用pip) 
import time
def f1(n):
  for i in range(n):
    print(gevent.getcurrent(), i)
    gevent.sleep(0.5)  # 為了提高協(xié)程效率,遇到阻塞類代碼,會(huì)自動(dòng)切換協(xié)程任務(wù)。
    # time.sleep(0.5)  # 阻塞類代碼必須使用gevent自己包裝的代碼,原生阻塞類代碼不會(huì)切換協(xié)程任務(wù)。 
              # 可以使用monkey.patch_all()將所有原生阻塞類代碼替換成gevent包裝的阻塞類代碼。 
def f2(n):
  for i in range(n):
    print(gevent.getcurrent(), i) # <Greenlet "Greenlet-0" at 0x7f4a09b34648: f1(5)> 0
    gevent.sleep(0.5)
    # time.sleep(0.5)
def f3(n):
  for i in range(n):
    print(gevent.getcurrent(), i)
    gevent.sleep(0.5)
    # time.sleep(0.5)
g1 = gevent.spawn(f1, 5) # gevent其實(shí)是對(duì)greenlet的封裝。
g2 = gevent.spawn(f2, 5) # 第一個(gè)參數(shù)f2表示協(xié)程執(zhí)行的具體任務(wù)(函數(shù)),第二個(gè)參數(shù)5表示要傳給f2的參數(shù)
g3 = gevent.spawn(f3, 5)
g1.join()  # 遇到阻塞類代碼,自動(dòng)切換協(xié)程任務(wù)。
g2.join()
g3.join()

運(yùn)行結(jié)果:

<Greenlet at 0x1985030: f1(5)> 0
<Greenlet at 0x1b431c8: f2(5)> 0
<Greenlet at 0x1b43140: f3(5)> 0
<Greenlet at 0x1985030: f1(5)> 1
<Greenlet at 0x1b431c8: f2(5)> 1
<Greenlet at 0x1b43140: f3(5)> 1
<Greenlet at 0x1985030: f1(5)> 2
<Greenlet at 0x1b431c8: f2(5)> 2
<Greenlet at 0x1b43140: f3(5)> 2
<Greenlet at 0x1985030: f1(5)> 3
<Greenlet at 0x1b431c8: f2(5)> 3
<Greenlet at 0x1b43140: f3(5)> 3
<Greenlet at 0x1985030: f1(5)> 4
<Greenlet at 0x1b431c8: f2(5)> 4
<Greenlet at 0x1b43140: f3(5)> 4

demo.py(gevent打補(bǔ)丁,monkey自動(dòng)替換原生阻塞類代碼。重要,常用):

import gevent # 需要安裝gevent模塊 sudo pip3 install gevent (python2.x使用pip)
import time
from gevent import monkey
# gevent打補(bǔ)丁
monkey.patch_all() # 將所有原生阻塞類代碼自動(dòng)替換成gevent包裝的阻塞類代碼。 
def f1(n):
  for i in range(n):
    print(gevent.getcurrent(), i)
    time.sleep(0.5) # 會(huì)自動(dòng)替換成 gevent.sleep(0.5)
def f2(n):
  for i in range(n):
    print(gevent.getcurrent(), i)
    time.sleep(0.5)
def f3(n):
  for i in range(n):
    print(gevent.getcurrent(), i)
    time.sleep(0.5)
# g1 = gevent.spawn(f1, 5)
# g2 = gevent.spawn(f2, 5)
# g3 = gevent.spawn(f3, 5)
# g1.join()
# g2.join()
# g3.join()
# 一種簡(jiǎn)便寫(xiě)法
gevent.joinall([
    gevent.spawn(f1, 5),
    gevent.spawn(f2, 5),
    gevent.spawn(f3, 5)
])

運(yùn)行結(jié)果:

<Greenlet at 0x22e0938: f1(5)> 0
<Greenlet at 0x22e09c0: f2(5)> 0
<Greenlet at 0x22e0a48: f3(5)> 0
<Greenlet at 0x22e0938: f1(5)> 1
<Greenlet at 0x22e09c0: f2(5)> 1
<Greenlet at 0x22e0a48: f3(5)> 1
<Greenlet at 0x22e0938: f1(5)> 2
<Greenlet at 0x22e09c0: f2(5)> 2
<Greenlet at 0x22e0a48: f3(5)> 2
<Greenlet at 0x22e0938: f1(5)> 3
<Greenlet at 0x22e09c0: f2(5)> 3
<Greenlet at 0x22e0a48: f3(5)> 3
<Greenlet at 0x22e0938: f1(5)> 4
<Greenlet at 0x22e09c0: f2(5)> 4
<Greenlet at 0x22e0a48: f3(5)> 4

demo.py(gevent底層原理):

import socket
import time
tcp_server_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_tcp.bind(("", 7899))
tcp_server_tcp.listen(128)
tcp_server_tcp.setblocking(False) # 設(shè)置套接字為非堵塞的方式。 (接收數(shù)據(jù)時(shí)如果沒(méi)有接到數(shù)據(jù)(阻塞)那么就拋異常,否則正常接收數(shù)據(jù)。)
client_socket_list = list() # 用于保存與客戶端連接的套接字。
while True:
  # time.sleep(0.5)
  try:
    new_socket, new_addr = tcp_server_tcp.accept() # 用拋異常的方式代替阻塞。
  except Exception as ret:
    print("---沒(méi)有新的客戶端到來(lái)---")
  else:
    print("---只要沒(méi)有產(chǎn)生異常,那么也就意味著 來(lái)了一個(gè)新的客戶端----")
    new_socket.setblocking(False) # 設(shè)置套接字為非堵塞的方式。 (如果需要阻塞就直接拋異常代替阻塞)
    client_socket_list.append(new_socket)
  for client_socket in client_socket_list:
    try:
      recv_data = client_socket.recv(1024)  # 用拋異常的方式代替阻塞。
    except Exception as ret:
      print("----這個(gè)客戶端還沒(méi)有發(fā)送過(guò)來(lái)數(shù)據(jù)----")
    else:
      if recv_data:
        # 對(duì)方發(fā)送過(guò)來(lái)數(shù)據(jù)
        print("----客戶端發(fā)送過(guò)來(lái)了數(shù)據(jù)-----")
      else:
        # 對(duì)方調(diào)用close 導(dǎo)致了 recv返回
        client_socket.close()
        client_socket_list.remove(client_socket)
        print("---客戶端已經(jīng)關(guān)閉----")

更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python進(jìn)程與線程操作技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門(mén)與進(jìn)階經(jīng)典教程》、《Python+MySQL數(shù)據(jù)庫(kù)程序設(shè)計(jì)入門(mén)教程》及《Python常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • 淺析form標(biāo)簽中的GET和POST提交方式區(qū)別

    淺析form標(biāo)簽中的GET和POST提交方式區(qū)別

    在HTML中,form表單的作用是收集標(biāo)簽中的內(nèi)容<form>...</form> 中間可以由訪問(wèn)者添加類似于文本,選擇,或者一些控制模塊等等.然后這些內(nèi)容將會(huì)被送到服務(wù)端
    2021-09-09
  • 關(guān)于Python中的閉包詳解

    關(guān)于Python中的閉包詳解

    大家好,本篇文章主要講的是關(guān)于Python中的閉包詳解,感興趣的同學(xué)感快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • 如何使用Pytorch搭建模型

    如何使用Pytorch搭建模型

    本來(lái)是只用Tenorflow的,但是因?yàn)門(mén)F有些Numpy特性并不支持,比如對(duì)數(shù)組使用列表進(jìn)行切片,所以只能轉(zhuǎn)戰(zhàn)Pytorch了(pytorch是支持的)。還好Pytorch比較容易上手,幾乎完美復(fù)制了Numpy的特性(但還有一些特性不支持),怪不得熱度上升得這么快。
    2020-10-10
  • Python中的xml與dict的轉(zhuǎn)換方法詳解

    Python中的xml與dict的轉(zhuǎn)換方法詳解

    這篇文章主要介紹了Python中的xml與dict的轉(zhuǎn)換方法詳解,xml 是指可擴(kuò)展標(biāo)記語(yǔ)言,一種標(biāo)記語(yǔ)言類似html,作用是傳輸數(shù)據(jù),而且不是顯示數(shù)據(jù)??梢宰远x標(biāo)簽,需要的朋友可以參考下
    2023-07-07
  • Python使用Beautiful?Soup(BS4)庫(kù)解析HTML和XML

    Python使用Beautiful?Soup(BS4)庫(kù)解析HTML和XML

    這篇文章介紹了Python使用Beautiful?Soup(BS4)庫(kù)解析HTML和XML的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Python日志極簡(jiǎn)配置示例

    Python日志極簡(jiǎn)配置示例

    這篇文章主要為大家介紹了Python日志極簡(jiǎn)配置示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • python實(shí)現(xiàn)提取jira bug列表的方法示例

    python實(shí)現(xiàn)提取jira bug列表的方法示例

    公司要求內(nèi)部每日整理jira bug發(fā)郵件,手動(dòng)執(zhí)行了一段時(shí)間,想著用自動(dòng)化的方式實(shí)現(xiàn),所以本文主要介紹了python實(shí)現(xiàn)提取jira bug列表,感興趣的可以了解一下
    2021-05-05
  • python定時(shí)檢查某個(gè)進(jìn)程是否已經(jīng)關(guān)閉的方法

    python定時(shí)檢查某個(gè)進(jìn)程是否已經(jīng)關(guān)閉的方法

    這篇文章主要介紹了python定時(shí)檢查某個(gè)進(jìn)程是否已經(jīng)關(guān)閉的方法,涉及Python進(jìn)程與時(shí)間的相關(guān)操作技巧,需要的朋友可以參考下
    2015-05-05
  • matplotlib 畫(huà)雙軸子圖無(wú)法顯示x軸的解決方法

    matplotlib 畫(huà)雙軸子圖無(wú)法顯示x軸的解決方法

    這篇文章主要介紹了matplotlib 畫(huà)雙軸子圖無(wú)法顯示x軸的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • python處理cookie詳解

    python處理cookie詳解

    Cookie用于服務(wù)器實(shí)現(xiàn)會(huì)話,用戶登錄及相關(guān)功能時(shí)進(jìn)行狀態(tài)管理,本文介紹了使用python處理cookie的方法,需要的朋友可以參考下
    2014-02-02

最新評(píng)論

永登县| 连江县| 京山县| 乌海市| 始兴县| 特克斯县| 琼海市| 福泉市| 奇台县| 富川| 育儿| 安龙县| 三门县| 成安县| 镇康县| 宁化县| 宽城| 古丈县| 哈尔滨市| 图木舒克市| 昆山市| 八宿县| 萍乡市| 和平区| 平江县| 清徐县| 宜州市| 廊坊市| 上杭县| 隆德县| 巴彦淖尔市| 达孜县| 海林市| 广东省| 罗平县| 永和县| 响水县| 汕头市| 绥江县| 霍城县| 锡林浩特市|