Python使用asyncio異步時(shí)的常見問題總結(jié)
1. 如何停止任務(wù)?
我們可以通過 asyncio.Task 對象上的 cancel() 方法取消任務(wù)。如果任務(wù)被取消,cancel() 方法返回 True,否則返回 False。
... # cancel the task was_cancelled = task.cancel()
如果任務(wù)已經(jīng)完成,則無法取消,cancel() 方法將返回 False,任務(wù)不會處于已取消狀態(tài)。
下次任務(wù)有機(jī)會運(yùn)行時(shí),它將引發(fā) CancelledError 異常。如果 CancelledError 異常未在包裝協(xié)程內(nèi)處理,任務(wù)將被取消。
否則,如果在包裝協(xié)程內(nèi)處理了 CancelledError 異常,任務(wù)將不會被取消。cancel() 方法還可以接受一個消息參數(shù),該參數(shù)將在 CancelledError 的內(nèi)容中使用。
我們可以探索如何取消正在運(yùn)行的任務(wù)。
在這個例子中,我們定義了一個任務(wù)協(xié)程,它報(bào)告一條消息然后阻塞片刻。
然后我們定義用作 asyncio 程序入口點(diǎn)的主協(xié)程。它報(bào)告一條消息,創(chuàng)建并安排任務(wù),然后等待片刻。
然后主協(xié)程在運(yùn)行時(shí)恢復(fù)和取消任務(wù)。它再等一會兒,讓任務(wù)響應(yīng)取消請求。然后主協(xié)程報(bào)告取消任務(wù)的請求是否成功。
任務(wù)被取消,然后完成。主協(xié)程然后在關(guān)閉程序之前報(bào)告任務(wù)的狀態(tài)是否已取消。
# SuperFastPython.com # example of canceling a running task import asyncio # define a coroutine for a task async def task_coroutine(): # report a message print('executing the task') # block for a moment await asyncio.sleep(1) # custom coroutine async def main(): # report a message print('main coroutine started') # create and schedule the task task = asyncio.create_task(task_coroutine()) # wait a moment await asyncio.sleep(0.1) # cancel the task was_cancelled = task.cancel() # report whether the cancel request was successful print(f'was canceled: {was_cancelled}') # wait a moment await asyncio.sleep(0.1) # check the status of the task print(f'canceled: {task.cancelled()}') # report a final message print('main coroutine done') # start the asyncio program asyncio.run(main())
運(yùn)行該示例會啟動 asyncio 事件循環(huán)并執(zhí)行 main() 協(xié)程。main() 協(xié)程報(bào)告一條消息,然后創(chuàng)建并調(diào)度任務(wù)協(xié)程。然后它暫停并等待片刻以允許任務(wù)協(xié)程開始運(yùn)行。任務(wù)運(yùn)行,報(bào)告消息并休眠一段時(shí)間。
main() 協(xié)程恢復(fù)和取消任務(wù)。它報(bào)告取消任務(wù)的請求已成功。然后它會休眠片刻,讓任務(wù)響應(yīng)要取消的請求。
task_coroutine() 恢復(fù)并引發(fā) CancelledError 異常,導(dǎo)致任務(wù)失敗并完成。main()協(xié)程恢復(fù)并報(bào)告任務(wù)是否處于取消狀態(tài)。在這種情況下,確實(shí)如此。
此示例突出顯示了取消正在運(yùn)行的任務(wù)的正常情況。
main coroutine started
executing the task
was canceled: True
canceled: True
main coroutine done
2. 如何等待任務(wù)完成?
我們可以通過直接等待 asyncio.Task 對象來等待任務(wù)完成。
... # wait for the task to finish await task
我們可以在一行中創(chuàng)建和等待任務(wù)。
... # create and wait for the task to finish await asyncio.create_task(custom_coro())
3. 如何從任務(wù)中獲取返回值?
我們可能需要將協(xié)程的值返回給調(diào)用者。我們可以通過等待從協(xié)程中檢索返回值。它假定正在等待的另一個協(xié)程返回一個值。
# coroutine that returns a value async def other_coro(): return 100
等待其他協(xié)程將掛起調(diào)用協(xié)程并安排其他協(xié)程執(zhí)行。一旦另一個協(xié)程完成,調(diào)用協(xié)程將恢復(fù)。返回值將從另一個協(xié)程傳遞給調(diào)用者。
... # execute coroutine and retrieve return value value = await other_coro()
協(xié)程可以包裝在 asyncio.Task 對象中。這有助于獨(dú)立執(zhí)行協(xié)程而無需當(dāng)前協(xié)程等待它。
這可以使用 asyncio.create_task() 函數(shù)來實(shí)現(xiàn)。
... # wrap coroutine in a task and schedule it for execution task = asyncio.create_task(other_coro())
有兩種方法可以從 asyncio.Task 中檢索返回值,它們是:
- 等待任務(wù)。
- 調(diào)用結(jié)果() 方法。
我們可以等待任務(wù)來檢索返回值。如果任務(wù)已安排或正在運(yùn)行,則調(diào)用者將掛起,直到任務(wù)完成并提供返回值。如果任務(wù)完成,將立即提供返回值。
... # get the return value from a task value = await task
與協(xié)程不同,我們可以多次等待任務(wù)而不會引發(fā)錯誤。
... # get the return value from a task value = await task # get the return value from a task value = await task
我們還可以通過調(diào)用 asyncio.Task 對象的 result() 方法來獲取任務(wù)的返回值。
... # get the return value from a task value = task.result()
這需要完成任務(wù)。如果不是,將引發(fā) InvalidStateError 異常。如果任務(wù)被取消,將引發(fā) CancelledError 異常。
4. 如何在后臺運(yùn)行任務(wù)?
我們可以通過將協(xié)程包裝在 asyncio.Task 對象中來在后臺運(yùn)行協(xié)程。這可以通過調(diào)用 asyncio.create_task() 函數(shù)并將其傳遞給協(xié)程來實(shí)現(xiàn)。
協(xié)程將被包裝在一個 Task 對象中,并被安排執(zhí)行。將返回任務(wù)對象,調(diào)用者不會掛起。
... # schedule the task for execution task = asyncio.create_task(other_coroutine())
至少在當(dāng)前協(xié)程出于任何原因掛起之前,任務(wù)不會開始執(zhí)行。我們可以通過暫停片刻讓任務(wù)開始運(yùn)行來幫助解決問題。這可以通過休眠零秒來實(shí)現(xiàn)。
... # suspend for a moment to allow the task to start running await asyncio.sleep(0)
這將暫停調(diào)用者一小會兒,并允許請求運(yùn)行的機(jī)會。這不是必需的,因?yàn)檎{(diào)用者可能會在未來某個時(shí)間暫停或作為正常執(zhí)行的一部分終止。一旦調(diào)用者沒有事情要做,我們也可以直接等待任務(wù)。
... # wait for the task to complete await task
5. 如何等待所有后臺任務(wù)?
我們可以等待 asyncio 程序中的所有獨(dú)立任務(wù)。這可以通過首先通過 asyncio.all_tasks() 函數(shù)獲取一組所有當(dāng)前正在運(yùn)行的任務(wù)來實(shí)現(xiàn)。
... # get a set of all running tasks all_tasks = asyncio.all_tasks()
這將返回一個集合,其中包含一個 asyncio.Task 對象,用于當(dāng)前正在運(yùn)行的每個任務(wù),包括 main() 協(xié)程。
我們不能直接等待這個集合,因?yàn)樗鼤肋h(yuǎn)阻塞,因?yàn)樗?dāng)前任務(wù)。因此,我們可以獲取當(dāng)前正在運(yùn)行的任務(wù)的 asyncio.Task 對象并將其從集合中刪除。
這可以通過首先調(diào)用 asyncio.current_task() 方法來獲取當(dāng)前協(xié)程的任務(wù),然后通過 remove() 方法將其從集合中刪除來實(shí)現(xiàn)。
... # get the current tasks current_task = asyncio.current_task() # remove the current task from the list of all tasks all_tasks.remove(current_task)
最后,我們可以等待剩余的任務(wù)集。這將掛起調(diào)用者,直到集合中的所有任務(wù)都完成。
... # suspend until all tasks are completed await asyncio.wait(all_tasks)
將它們結(jié)合在一起,下面添加到 main() 協(xié)程末尾的代碼片段將等待所有后臺任務(wù)完成。
... # get a set of all running tasks all_tasks = asyncio.all_tasks() # get the current tasks current_task = asyncio.current_task() # remove the current task from the list of all tasks all_tasks.remove(current_task) # suspend until all tasks are completed await asyncio.wait(all_tasks)
到此這篇關(guān)于Python使用asyncio異步時(shí)的常見問題總結(jié)的文章就介紹到這了,更多相關(guān)Python asyncio異步內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python使用asyncio實(shí)現(xiàn)異步操作的示例
- Python中asyncio的多種用法舉例(異步同步)
- Python使用asyncio處理異步編程的代碼示例
- Python使用asyncio包實(shí)現(xiàn)異步編程方式
- Python異步庫asyncio、aiohttp詳解
- python協(xié)程異步IO中asyncio的使用
- Python使用asyncio標(biāo)準(zhǔn)庫對異步IO的支持
- Python協(xié)程異步爬取數(shù)據(jù)(asyncio+aiohttp)實(shí)例
- Python asyncio異步編程常見問題小結(jié)
- Python asyncio異步編程簡單實(shí)現(xiàn)示例
- Python中asyncio庫實(shí)現(xiàn)異步編程的示例
相關(guān)文章
python中如何利用matplotlib畫多個并列的柱狀圖
python是一個很有趣的語言,可以在命令行窗口運(yùn)行,下面這篇文章主要給大家介紹了關(guān)于python中如何利用matplotlib畫多個并列的柱狀圖的相關(guān)資料,需要的朋友可以參考下2022-01-01如何通過雪花算法用Python實(shí)現(xiàn)一個簡單的發(fā)號器
這篇文章主要介紹了如何通過雪花算法用Python實(shí)現(xiàn)一個簡單的發(fā)號器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07對python PLT中的image和skimage處理圖片方法詳解
今天小編就為大家分享一篇對python PLT中的image和skimage處理圖片方法詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01python+pygame簡單畫板實(shí)現(xiàn)代碼實(shí)例
這篇文章主要介紹了python+pygame簡單畫板實(shí)現(xiàn)代碼實(shí)例,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12python cookie反爬處理的實(shí)現(xiàn)
這篇文章主要介紹了python cookie反爬處理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11python2.7讀取文件夾下所有文件名稱及內(nèi)容的方法
python,本身來說是一門高級編程語言,python它入門簡單,有基礎(chǔ)的學(xué)起來很快就能有簡單的應(yīng)用,但是在非常高的抽象計(jì)算中,高級的python程序設(shè)計(jì)也是非常難學(xué)的。接下來給大家介紹python2.7讀取文件夾下所有文件名稱及內(nèi)容的方法,一起看看吧2018-02-02Windows下pycharm創(chuàng)建Django 項(xiàng)目(虛擬環(huán)境)過程解析
這篇文章主要介紹了Windows下pycharm創(chuàng)建Django 項(xiàng)目(虛擬環(huán)境)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09python中數(shù)組和矩陣乘法及使用總結(jié)(推薦)
這篇文章主要介紹了python中數(shù)組和矩陣乘法及使用總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05