溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python異步之怎么保護(hù)任務(wù)免于取消

發(fā)布時(shí)間:2023-05-12 14:18:38 來源:億速云 閱讀:130 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“Python異步之怎么保護(hù)任務(wù)免于取消”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Python異步之怎么保護(hù)任務(wù)免于取消”吧!

Asyncio 任務(wù)可以通過調(diào)用它們的 cancel() 方法來取消。我們可以通過將任務(wù)包裝在對 asyncio.shield() 的調(diào)用中來保護(hù)任務(wù)不被取消。

1. 什么是 Asyncio shield()

asyncio.shield() 函數(shù)在 Future 中包裝了一個(gè)可等待對象,它將吸收要取消的請求。

這意味著被屏蔽的未來可以傳遞給可能嘗試取消它的任務(wù),并且取消請求看起來像是成功的,除了被屏蔽的任務(wù)或協(xié)程將繼續(xù)運(yùn)行。

它可能在 asyncio 程序中很有用,其中某些任務(wù)可以取消,但其他任務(wù)(可能具有更高優(yōu)先級)則不能。

它也可能在某些任務(wù)可以安全取消的程序中很有用,例如那些在設(shè)計(jì)時(shí)考慮了 asyncio 的任務(wù),而其他任務(wù)則不能安全終止,因此必須避免取消。

現(xiàn)在我們知道了 asyncio.shield() 是什么,讓我們看看如何使用它。

2. 如何使用 Asyncio shield()

asyncio.shield() 函數(shù)將保護(hù)另一個(gè)任務(wù)或協(xié)程不被取消。它以一個(gè)可等待對象作為參數(shù)并返回一個(gè) asyncio.Future 對象。

然后可以直接等待 Future 對象或?qū)⑵鋫鬟f給另一個(gè)任務(wù)或協(xié)程。

...
# shield a task from cancellation
shielded = asyncio.shield(task)
# await the shielded task
await shielded

返回的 Future 可以通過調(diào)用 cancel() 方法取消。

如果內(nèi)部任務(wù)正在運(yùn)行,請求將被報(bào)告為成功。

...
# cancel a shielded task
was_canceld = shielded.cancel()

任何等待 Future 對象的協(xié)程都會引發(fā) asyncio.CancelledError,這可能需要處理。

...
try:
	# await the shielded task
	await asyncio.shield(task)
except asyncio.CancelledError:
	# ...

重要的是,對 Future 對象的取消請求不會傳播到內(nèi)部任務(wù)。這意味著取消請求被護(hù)盾吸收了。

...
# create a task
task = asyncio.create_task(coro())
# create a shield
shield = asyncio.shield(task)
# cancel the shield (does not cancel the task)
shield.cancel()

如果協(xié)程被提供給 asyncio.shield() 函數(shù),它將被包裝在 asyncio.Task() 中并立即調(diào)度。

這意味著不需要等待屏蔽來讓內(nèi)部協(xié)程運(yùn)行。

如果被屏蔽的任務(wù)被取消,取消請求將向上傳播到屏蔽,屏蔽也將被取消。

...
# create a task
task = asyncio.create_task(coro())
# create a shield
shield = asyncio.shield(task)
# cancel the task (also cancels the shield)
task.cancel()

現(xiàn)在我們知道如何使用 asyncio.shield() 函數(shù),讓我們看一些有效的例子。

3. 示例

我們可以探索如何使用 asyncio.shield() 來保護(hù)任務(wù)不被取消。

在這個(gè)例子中,我們定義了一個(gè)簡單的協(xié)程任務(wù),它接受一個(gè)整數(shù)參數(shù),休眠一秒鐘,然后返回參數(shù)。然后可以創(chuàng)建協(xié)程并將其安排為任務(wù)。

我們可以定義第二個(gè)協(xié)程,它接受一個(gè)任務(wù),休眠幾分之一秒,然后取消提供的任務(wù)。

在主協(xié)程中,我們可以屏蔽第一個(gè)任務(wù),然后將其傳遞給第二個(gè)任務(wù),然后等待被屏蔽的任務(wù)。

期望是屏蔽將被取消并保持內(nèi)部任務(wù)完好無損。取消將中斷主協(xié)程。我們可以在程序結(jié)束時(shí)檢查內(nèi)部任務(wù)的狀態(tài),我們希望它已經(jīng)正常完成,而不管屏蔽上的取消請求如何。

# SuperFastPython.com
# example of using asyncio shield to protect a task from cancellation
import asyncio
# define a simple asynchronous
async def simple_task(number):
    # block for a moment
    await asyncio.sleep(1)
    # return the argument
    return number
# cancel the given task after a moment
async def cancel_task(task):
    # block for a moment
    await asyncio.sleep(0.2)
    # cancel the task
    was_cancelled = task.cancel()
    print(f'cancelled: {was_cancelled}')
# define a simple coroutine
async def main():
    # create the coroutine
    coro = simple_task(1)
    # create a task
    task = asyncio.create_task(coro)
    # created the shielded task
    shielded = asyncio.shield(task)
    # create the task to cancel the previous task
    asyncio.create_task(cancel_task(shielded))
    # handle cancellation
    try:
        # await the shielded task
        result = await shielded
        # report the result
        print(f'>got: {result}')
    except asyncio.CancelledError:
        print('shielded was cancelled')
    # wait a moment
    await asyncio.sleep(1)
    # report the details of the tasks
    print(f'shielded: {shielded}')
    print(f'task: {task}')
# start
asyncio.run(main())

運(yùn)行示例首先創(chuàng)建 main() 協(xié)程并將其用作應(yīng)用程序的入口點(diǎn)。創(chuàng)建任務(wù)協(xié)程,然后將其包裝并安排在任務(wù)中。然后該任務(wù)就不會被取消。

然后將屏蔽的任務(wù)傳遞給 cancel_task() 協(xié)程,該協(xié)程包裝在任務(wù)中并進(jìn)行調(diào)度。主協(xié)程然后等待受保護(hù)的任務(wù),該任務(wù)需要 CancelledError 異常。

任務(wù)運(yùn)行片刻然后休眠。取消任務(wù)運(yùn)行片刻,休眠,恢復(fù)然后取消屏蔽任務(wù)。取消請求報(bào)告它已成功。

這會在受保護(hù)的 Future 中引發(fā) CancelledError 異常,但不會在內(nèi)部任務(wù)中引發(fā)。

main() 協(xié)程恢復(fù)并響應(yīng) CancelledError 異常,報(bào)告一條消息。然后它會睡一會兒。任務(wù)恢復(fù)、完成并返回一個(gè)值。

最后,main() 協(xié)程恢復(fù),并報(bào)告被屏蔽的未來和內(nèi)部任務(wù)的狀態(tài)。我們可以看到屏蔽的未來被標(biāo)記為已取消,而內(nèi)部任務(wù)被標(biāo)記為正常完成并提供返回值。

此示例突出顯示了如何使用防護(hù)罩來成功保護(hù)內(nèi)部任務(wù)不被取消。

cancelled: True
shielded was cancelled
shielded: <Future cancelled>
task: <Task finished name='Task-2' coro=<simple_task() done, defined at ...> result=1>

感謝各位的閱讀,以上就是“Python異步之怎么保護(hù)任務(wù)免于取消”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Python異步之怎么保護(hù)任務(wù)免于取消這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI