python協程與非同步協程

2021-08-22 01:15:34 字數 2867 閱讀 8663

在前面幾個部落格中我們一一對應解決了消費者消費的速度跟不上生產者,浪費我們大量的時間去等待的問題,在這裡,針對業務邏輯比較耗時間的問題,我們還有除了多程序之外更優的解決方式,那就是協程和非同步協程。在引入這個概念之前我們先看   看這個圖:

從這個我們可以看出來,假如來了9個任務,即使我們開了多程序,在業務的執行過程中我們依舊是同步操作,所以執行完這一波任務我們一共需要9s,雖然比單程序快了3倍,但是在機器條件可以(肯定可以)的情況下,我們如何更加合理的利用給我們的資源呢?於是非同步協程的優勢就來了:

根據這張圖我們可以看出來,在任務1執行完業務邏輯1的時候,任務2就可以開始執行,這樣當任務2執行完業務邏輯1的時候,任務3就開始執行了,這樣我們3個程序,總共耗時只需要5s,比上面同步的方式快了足足4s,省去了等待的時間,讓模組之間銜接和呼叫更加充分。

在python中,我們先介紹一下2.0的協程:gevent的使用,在python3.4之後新增了syncoio的使用,這篇部落格我們就專門針對業務邏輯部分進行深度的優化:

gevent是第三方庫,通過greenlet實現協程,其基本思想是:

當乙個greenlet遇到io操作時,比如訪問網路,就自動切換到其他的greenlet,等到io操作完成,再在適當的時候切換回來繼續執行。由於io操作非常耗時,經常使程式處於等待狀態,有了gevent為我們自動切換協程,就保證總有greenlet在執行,而不是等待io(引用)。

比如下面**:

from gevent import monkey

monkey.patch_all()

import gevent

import time

# todo 此處是業務邏輯操作

def logicdel(data):

time.sleep(2)

print('im running',data)

if __name__ == '__main__':

# 在這裡我們宣告幾個任務,把任務放到乙個list中去做分配排程

tasks=[gevent.spawn(logicdel,data) for data in range(9)]

gevent.joinall(tasks)

我們可以看到我們在乙個tasks裡面9個任務,每個任務執行都要sleep2秒,如果是阻塞式執行就需要18s,但是我們加入了協程,所有的任務完成只需要2s,其中原理和上圖(非同步載入圖)一樣,這裡就不贅述了。

然而有時候我們**業務邏輯中乙個業務執行不只有乙個任務,其中每個任務之間還有排程依賴的關係,這時候我們的gevent就顯得有點力不從心了,這裡就引進了python3.4之後的乙個自帶的包asyncio——非同步協程。

asyncio的程式設計模型就是乙個訊息迴圈。我們從asyncio模組中直接獲取乙個eventloop的引用,然後把需要執行的協程扔到eventloop中執行,就實現了非同步io。用asyncio實現hello world**如下:

import threading

import asyncio

@asyncio.coroutine

def hello():

print('hello world11111111 (%s)' % threading.currentthread())

yield from asyncio.sleep(1)

print('hello again22222222 (%s)' % threading.currentthread())

loop = asyncio.get_event_loop()

tasks = [hello(), hello()]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

其中每個tasks都是非阻塞式的,當然這個還是沒有解決乙個業務有多個任務且每個任務之間存在依賴關係應當怎麼解決的問題,因為我們還沒有引用async await:

import asyncio

import time

# borrowed from

# @asyncio.coroutine

async def myslep(n):

print(n)

time.sleep(10)

asyncio.sleep(5)

async def countdown(number, n):

while n > 0:

print('t-minus', n, '({})'.format(number))

# await myslep(n)

tasks2=

await asyncio.ensure_future(myslep(n))

# time.sleep(2)

n -= 1

loop = asyncio.get_event_loop()

tasks = [

asyncio.ensure_future(countdown("a", 2)),

asyncio.ensure_future(countdown("b", 3)),

asyncio.ensure_future(countdown("c", 3)),

]loop.run_until_complete(asyncio.wait(tasks))

loop.close()

python 非同步與協程學習

參考 深入理解python非同步程式設計 理解 python asyncio 1 非同步非租塞 以春運火車票為例,非同步 你使用分流軟體搶票,設定好時間型別,軟體自動執行 非阻塞 你不用等搶票結果,可以去做別的事 如何獲得結果 輪詢 每隔一段時間,你看一下搶到票沒有 事件通知 設定搶到票,郵件或者簡...

http 協程與非同步 Python

協程是啥 簡單來說,協程是一種基於執行緒之上,但又比執行緒更加輕量級的存在。對於系統核心來說,協程具有不可見的特性,所以這種由 程式設計師自己寫程式來管理的輕量級執行緒又常被稱作 使用者空間執行緒 協程比多執行緒好在哪 適用場景 協程適用於被阻塞的,且需要大量併發的場景。不適用場景 協程不適用於存在...

協程巢狀協程

import asyncio import functools 第三層協程 async def test1 print 我是test1 await asyncio.sleep 1 print test1已經睡了1秒 await asyncio.sleep 3 print test1又睡了3秒 ret...