asyncio非同步的基礎理解

2021-10-02 15:27:50 字數 1428 閱讀 4277

大概半年前開始使用asyncio。最初開始接觸asyncio是受到「車主」的影響,因為他說他的專案基本都是使用的aio的方式,例如aioredis,aiokafka,aiomysql等。

但是之前對asyncio的用法一直有誤解,就連之前寫的非同步消費埋點資料的專案看似用了async的語法,但實際上並沒有真正的實現非同步。下面通過最基本簡單的例子來糾正之前理解上的錯誤:

import asyncio

async def main():

print('hello ...')

await asyncio.sleep(5)

print('... world!')

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

loop.close()

錯誤的理解:

既然是非同步的執行,那這裡其實有兩個協程,乙個是main(),乙個是asyncio.sleep(5)。當asyncio.sleep(5)在執行的時候控制權應該交回給main(),所以print(』… world!』)應該在sleep之前列印出來。

但實際上在執行的時候發現print(』… world!』)並沒有立刻被列印,而是在等待了5s之後才被列印出來。這裡看上去有多個協程,而且asyncio.run的使用方法也沒錯,為什麼並沒有實現真正的非同步呢?

正確的理解:

參考了stack overflow上的解釋,這裡並沒有真正非同步的原因是:asyncio的eventloop當中只有main()這乙個task,並沒有其他的task了。asyncio.run(main())決定了eventloop中只loop了main(),所以雖然asyncio.sleep(5)是nonblocking的,但是並沒有其他的task可以被切換,所以控制權就沒有辦法往外移交,直到main()剩餘的**執行完畢。所以這裡我們看上去main()就像乙個blocking的**一樣被執行。

所以說,如果我們要實現真正的非同步,那eventloop中至少應該有兩個以上的協程。我們再加乙個試試:

import asyncio

async def main():

print('hello ...')

await asyncio.sleep(5)

print('... world!')

loop = asyncio.get_event_loop()

loop.run_until_complete(asyncio.gather(*[main(), main()]))

loop.close()

這個時候就看到了非同步的輸出結果:

hello ...

hello ...

... world!

... world!

這才是使用非同步的正確姿勢。

asyncio 非同步任務

前言 python由於gil 全域性鎖 的存在,不能發揮多核的優勢,其效能一直飽受詬病。然而在io密集型的網路程式設計裡,非同步處理比同步處理能提公升成百上千倍的效率,彌補了python效能方面的短板,如最新的微服務框架japronto,resquests per second可達百萬級。pytho...

Python3 asyncio非同步框架 基礎知識

有些問題 async defrun await asyncio.ensure future p.packing 非阻塞 await asyncio.gather tasks 阻塞先解釋幾個名詞 同步與非同步 同步需要等待io返回的結果,非同步不需要io返回的結果 阻塞與非阻塞 阻塞 程式要等待,非阻...

Python中的非同步程式設計 Asyncio

如果你已經決定要理解 python 的非同步部分,歡迎來到我們的 asyncio how to 注 哪怕連異動正規化的存在都不知道的情況下,你也可以成功地使用 python。但是,如果你對底層執行模式感興趣的話,asyncio 絕對值得檢視。非同步是怎麼一回事?在傳統的順序程式設計中,所有傳送給直譯...