欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

實現多任務:進程消耗的資源最大,線程消耗的資源次之,協(xié)程消耗的資源最少(單線程)。

gevent實現協(xié)程,gevent是通過阻塞代碼(例如網絡延遲等)來自動切換要執(zhí)行的任務,所以在進行IO密集型程序時(例如爬蟲),使用gevent可以提高效率(有效利用網絡延遲的時間去執(zhí)行其他任務)。

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

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

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

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

demo.py(greenlet實現協(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中的任務。
    time.sleep(0.5)
def test2():
  while True:
    print("---B--")
    gr1.switch()  # 切換到gr1中的任務。
    time.sleep(0.5)
gr1 = greenlet(test1) # greenlet 底層封裝了yield。
gr2 = greenlet(test2)
#切換到gr1中運行
gr1.switch()

demo.py(gevent實現協(xié)程,封裝了greenlet,遇到阻塞代碼自動切換協(xié)程任務):

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é)程效率,遇到阻塞類代碼,會自動切換協(xié)程任務。
    # time.sleep(0.5)  # 阻塞類代碼必須使用gevent自己包裝的代碼,原生阻塞類代碼不會切換協(xié)程任務。 
              # 可以使用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其實是對greenlet的封裝。
g2 = gevent.spawn(f2, 5) # 第一個參數f2表示協(xié)程執(zhí)行的具體任務(函數),第二個參數5表示要傳給f2的參數
g3 = gevent.spawn(f3, 5)
g1.join()  # 遇到阻塞類代碼,自動切換協(xié)程任務。
g2.join()
g3.join()

運行結果:

<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打補丁,monkey自動替換原生阻塞類代碼。重要,常用):

import gevent # 需要安裝gevent模塊 sudo pip3 install gevent (python2.x使用pip)
import time
from gevent import monkey
# gevent打補丁
monkey.patch_all() # 將所有原生阻塞類代碼自動替換成gevent包裝的阻塞類代碼。 
def f1(n):
  for i in range(n):
    print(gevent.getcurrent(), i)
    time.sleep(0.5) # 會自動替換成 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()
# 一種簡便寫法
gevent.joinall([
    gevent.spawn(f1, 5),
    gevent.spawn(f2, 5),
    gevent.spawn(f3, 5)
])

運行結果:

<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) # 設置套接字為非堵塞的方式。 (接收數據時如果沒有接到數據(阻塞)那么就拋異常,否則正常接收數據。)
client_socket_list = list() # 用于保存與客戶端連接的套接字。
while True:
  # time.sleep(0.5)
  try:
    new_socket, new_addr = tcp_server_tcp.accept() # 用拋異常的方式代替阻塞。
  except Exception as ret:
    print("---沒有新的客戶端到來---")
  else:
    print("---只要沒有產生異常,那么也就意味著 來了一個新的客戶端----")
    new_socket.setblocking(False) # 設置套接字為非堵塞的方式。 (如果需要阻塞就直接拋異常代替阻塞)
    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("----這個客戶端還沒有發(fā)送過來數據----")
    else:
      if recv_data:
        # 對方發(fā)送過來數據
        print("----客戶端發(fā)送過來了數據-----")
      else:
        # 對方調用close 導致了 recv返回
        client_socket.close()
        client_socket_list.remove(client_socket)
        print("---客戶端已經關閉----")

更多關于Python相關內容感興趣的讀者可查看本站專題:《Python進程與線程操作技巧總結》、《Python數據結構與算法教程》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》、《Python入門與進階經典教程》、《Python+MySQL數據庫程序設計入門教程》及《Python常見數據庫操作技巧匯總

希望本文所述對大家Python程序設計有所幫助。

相關文章

  • Python time庫基本使用方法分析

    Python time庫基本使用方法分析

    這篇文章主要介紹了Python time庫基本使用方法,結合實例形式分析了Python time模塊基本功能、控制符、使用方法與操作注意事項,需要的朋友可以參考下
    2019-12-12
  • Python實現設置windows桌面壁紙代碼分享

    Python實現設置windows桌面壁紙代碼分享

    這篇文章主要介紹了Python實現設置windows桌面壁紙,本文直接給出實現代碼,需要的朋友可以參考下
    2015-03-03
  • 利用Python制作一個愚人節(jié)整蠱消息框

    利用Python制作一個愚人節(jié)整蠱消息框

    又到了一年一度的愚人節(jié)了,本文小編為大家準備了用Python語言制作的愚人節(jié)整蠱消息框,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2023-04-04
  • django自帶的server 讓外網主機訪問方法

    django自帶的server 讓外網主機訪問方法

    今天小編就為大家分享一篇django自帶的server 讓外網主機訪問方法。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Python算法之棧(stack)的實現

    Python算法之棧(stack)的實現

    這篇文章主要介紹了Python算法之棧(stack)的實現,非常實用,需要的朋友可以參考下
    2014-08-08
  • openCV中值濾波和均值濾波的代碼實現

    openCV中值濾波和均值濾波的代碼實現

    在我們生活中的有很多時候都可以用到濾波,例如美顏的磨皮功能,本文就詳細的介紹了openCV中值濾波和均值濾波的代碼實現,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 深入了解Python枚舉類型的相關知識

    深入了解Python枚舉類型的相關知識

    這篇文章主要介紹了深入了解Python枚舉類型的相關知識,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • django中F與Q查詢的使用

    django中F與Q查詢的使用

    一般查詢都是單條件查詢,F和Q是組合條件查詢,本文主要介紹了django中F與Q查詢的使用,感興趣的可以了解一下
    2021-06-06
  • 對Python實現累加函數的方法詳解

    對Python實現累加函數的方法詳解

    今天小編就為大家分享一篇對Python實現累加函數的方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • python logging模塊的使用詳解

    python logging模塊的使用詳解

    這篇文章主要介紹了python logging模塊的使用,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-10-10

最新評論