python并发编程6-协程
生活随笔
收集整理的這篇文章主要介紹了
python并发编程6-协程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、基礎
# 進程 啟動多個進程 進程之間是由操作系統(時間片輪轉)負責調用 # 線程 啟動多個線程 真正被CPU執行的最小單位是線程# 開啟一個線程 創建一個線程 寄存器 堆棧# 關閉一個線程 等都需要時間 # 協程:本質上是一個線程# 能夠在多個任務之間切換來節省一些IO時間# 協程切換也需要時間,但是遠遠小于線程進程開銷時間 # 實現并發的手段2 協程應用背景
import time '''1''' def consumer(): # 生成器函數print(123)while True:x=yieldprint('**',x) c=consumer() # c為生成器,此時函數并沒有執行 next(c) c.send(1)程序執行順序:
程序運行結果:
3 在一個程序上進行兩個任務的切換
'''2 在一個程序上進行兩個任務的切換''' def consumer(): # 生成器函數while True:x=yieldtime.sleep(1)print('處理了數據',x) def producer():c=consumer()next(c)for i in range(3):time.sleep(1)print('生產了數據:',i)c.send(i) producer()程序執行順序:
程序運行結果:
4、協程切換:切換后接著執行-greenlet模塊
'''3 協程切換:切換后接著執行''' from greenlet import greenlet # 真正的協程模塊就是使用greenlet完成的切換 def eat():print('eating start')g2.switch()print('eating end')g2.switch() def play():print('playing start')g1.switch()print('playing end') g1=greenlet(eat) g2=greenlet(play) g1.switch()程序執行順序:
程序執行結果:
5 協程切換 gevent
# spawn(func) 大量生產 # join() # .value 得到方法的返回值?例子1:
import geventdef eat():print('eating start')gevent.sleep(1)print('eating end') def play():print('playing start')gevent.sleep(1)print('playing end') g1=gevent.spawn(eat) # 開啟一個協程 g2=gevent.spawn(play) g1.join() # 主線程等待g1結束 g2.join() # 主線程等待g2結束?運行結果:
協程對time.sleep(1)不會有效果。只對gevent.sleep(1)有效果。除非用monkey模塊。如下:
from gevent import monkey;monkey.patch_all() # 有了這句代碼,自動會把IO操作打包。否則就需要用gevent.sleep() import gevent def eat():print('eat:', threading.current_thread().getName()) #DummyThread-1假線程print('eating start')time.sleep(1) # IO事件print('eating end') def play():print('play:', threading.current_thread().getName())print('playing start')time.sleep(1) # IO事件print('playing end') g1=gevent.spawn(eat) # 開啟一個協程 g2=gevent.spawn(play) g1.join() g2.join()運行結果:
協程屬于偽線程
6 同步和異步
# 進程和線程的狀態切換是由操作系統完成 # 協程任務之間的切換是由程序(代碼)完成。# 只有遇到協程模塊能識別的IO操作的時候,程序才會進行任務切換,實現并發的效果#同步和異步:在高IO之間使用協程操作 # 協程 : 能夠在一個線程中實現并發效果的概念# 能夠規避一些任務中的IO操作# 在任務的執行過程中檢測到IO就切換到其他任務?
from gevent import monkey;monkey.patch_all() # 必須寫在import其他模塊之前 import time import gevent def task():time.sleep(1)print(12345) def sync():for i in range(10):task() def async():g_lst=[]for i in range(10):g=gevent.spawn(task)g_lst.append(g)# for g in g_lst:g.join()gevent.joinall(g_lst) sync() async()運行結果:
輸出過程:先一秒一秒輸出12345.輸出四個后。同時輸出5個12345
7 利用協程實現socket聊天
server模塊:
import socket from gevent import monkey;monkey.patch_all() import gevent def talk(conn):conn.send(b'hello')print(conn.recv(1024).decode('utf-8'))conn.close() sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True:conn,addr=sk.accept()gevent.spawn(talk,conn) sk.close()client模塊:
?
運行結果:
進程,線程,協程個數關系
總結
以上是生活随笔為你收集整理的python并发编程6-协程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬虫5-BeautifulSoup模块简
- 下一篇: python 手动拼接json数据