山西企業(yè)網(wǎng)站建設(shè)網(wǎng)站注冊(cè)地址
我們可以反省在 asyncio 事件循環(huán)中運(yùn)行的任務(wù)。這可以通過(guò)為當(dāng)前運(yùn)行的任務(wù)和所有正在運(yùn)行的任務(wù)獲取一個(gè) asyncio.Task 對(duì)象來(lái)實(shí)現(xiàn)。
1. 如何獲取當(dāng)前任務(wù)
我們可以通過(guò) asyncio.current_task() 函數(shù)獲取當(dāng)前任務(wù)。此函數(shù)將為當(dāng)前正在運(yùn)行的任務(wù)返回一個(gè)任務(wù)對(duì)象。
...
# get the current task
task = asyncio.current_task()
這將為當(dāng)前正在運(yùn)行的任務(wù)返回一個(gè)任務(wù)對(duì)象。這可能是:
- 傳遞給 asyncio.run() 的主協(xié)程。
- 通過(guò) asyncio.create_task() 在 asyncio 程序中創(chuàng)建和調(diào)度的任務(wù)。
一個(gè)任務(wù)可以創(chuàng)建并運(yùn)行另一個(gè)協(xié)程(例如,不包含在任務(wù)中)。從協(xié)程中獲取當(dāng)前任務(wù)將為正在運(yùn)行的任務(wù)返回一個(gè) Task 對(duì)象,但不會(huì)返回當(dāng)前正在運(yùn)行的協(xié)程。
如果協(xié)程或任務(wù)需要有關(guān)自身的詳細(xì)信息,例如用于日志記錄的任務(wù)名稱(chēng),則獲取當(dāng)前任務(wù)會(huì)很有幫助。
我們可以探索如何為用于啟動(dòng) asyncio 程序的主協(xié)程獲取 Task 實(shí)例。下面的示例定義了一個(gè)用作程序入口點(diǎn)的協(xié)程。它報(bào)告一條消息,然后獲取當(dāng)前任務(wù)并報(bào)告其詳細(xì)信息。
這是第一個(gè)重要的示例,因?yàn)樗鼜?qiáng)調(diào)所有協(xié)程都可以作為異步事件循環(huán)中的任務(wù)進(jìn)行訪問(wèn)。
下面列出了完整的示例。
# SuperFastPython.com
# example of getting the current task from the main coroutine
import asyncio# define a main coroutine
async def main():# report a messageprint('main coroutine started')# get the current tasktask = asyncio.current_task()# report its detailsprint(task)# start the asyncio program
asyncio.run(main())
運(yùn)行該示例首先創(chuàng)建主協(xié)程并使用它來(lái)啟動(dòng) asyncio 程序。main() 協(xié)程運(yùn)行并首先報(bào)告一條消息。
然后它檢索當(dāng)前任務(wù),這是一個(gè)代表自身的任務(wù)對(duì)象,即當(dāng)前正在運(yùn)行的協(xié)程。然后它會(huì)報(bào)告當(dāng)前正在運(yùn)行的任務(wù)的詳細(xì)信息。
我們可以看到該任務(wù)具有第一個(gè)任務(wù)的默認(rèn)名稱(chēng)“Task-1”,并且正在執(zhí)行 main() 協(xié)程,即當(dāng)前正在運(yùn)行的協(xié)程。
這突出表明我們可以使用 asyncio.current_task() 函數(shù)來(lái)訪問(wèn)當(dāng)前正在運(yùn)行的協(xié)程的任務(wù)對(duì)象,該對(duì)象自動(dòng)包裝在任務(wù)對(duì)象中。
main coroutine started
<Task pending name='Task-1' coro=<main() running at ...> cb=[_run_until_complete_cb() at ...]>
2. 如何獲取所有任務(wù)
我們可能需要訪問(wèn)異步程序中的所有任務(wù)。這可能有很多原因,例如:
- 反省程序的當(dāng)前狀態(tài)或復(fù)雜性。
- 記錄所有正在運(yùn)行的任務(wù)的詳細(xì)信息。
- 查找可以查詢(xún)或取消的任務(wù)。
我們可以通過(guò) asyncio.all_tasks() 函數(shù)在 asyncio 程序中獲取一組所有已計(jì)劃和正在運(yùn)行(尚未完成)的任務(wù)。
...
# get all tasks
tasks = asyncio.all_tasks()
這將返回 asyncio 程序中所有任務(wù)的集合。它是一個(gè)集合,因此每個(gè)任務(wù)只代表一次。
如果出現(xiàn)以下情況,將包括一項(xiàng)任務(wù):
- 任務(wù)已安排但尚未運(yùn)行。
- 該任務(wù)當(dāng)前正在運(yùn)行(例如,但當(dāng)前已暫停)
該集合還將包括當(dāng)前正在運(yùn)行的任務(wù)的任務(wù),例如正在執(zhí)行調(diào)用 asyncio.all_tasks() 函數(shù)的協(xié)程的任務(wù)。
另外,回想一下用于啟動(dòng) asyncio 程序的 asyncio.run() 方法會(huì)將提供的協(xié)程包裝在任務(wù)中。這意味著所有任務(wù)的集合將包括程序入口點(diǎn)的任務(wù)。
我們可以探索在一個(gè) asyncio 程序中有很多任務(wù)的情況,然后得到一組所有任務(wù)。
在此示例中,我們首先創(chuàng)建 10 個(gè)任務(wù),每個(gè)任務(wù)包裝并運(yùn)行相同的協(xié)程。主協(xié)程然后獲取程序中計(jì)劃或運(yùn)行的所有任務(wù)的集合并報(bào)告它們的詳細(xì)信息。
下面列出了完整的示例。
# SuperFastPython.com
# example of starting many tasks and getting access to all tasks
import asyncio# coroutine for a task
async def task_coroutine(value):# report a messageprint(f'task {value} is running')# block for a momentawait asyncio.sleep(1)# define a main coroutine
async def main():# report a messageprint('main coroutine started')# start many tasksstarted_tasks = [asyncio.create_task(task_coroutine(i)) for i in range(10)]# allow some of the tasks time to startawait asyncio.sleep(0.1)# get all taskstasks = asyncio.all_tasks()# report all tasksfor task in tasks:print(f'> {task.get_name()}, {task.get_coro()}')# wait for all tasks to completefor task in started_tasks:await task# start the asyncio program
asyncio.run(main())
運(yùn)行該示例首先創(chuàng)建主協(xié)程并使用它來(lái)啟動(dòng) asyncio 程序。main() 協(xié)程運(yùn)行并首先報(bào)告一條消息。然后它創(chuàng)建并安排 10 個(gè)包裝自定義協(xié)程的任務(wù)。然后 main() 協(xié)程會(huì)阻塞片刻以允許任務(wù)開(kāi)始運(yùn)行。任務(wù)開(kāi)始運(yùn)行,每個(gè)任務(wù)報(bào)告一條消息,然后休眠。
main() 協(xié)程恢復(fù)并獲取程序中所有任務(wù)的列表。然后它報(bào)告每個(gè)的名稱(chēng)和協(xié)程。最后,它枚舉已創(chuàng)建的任務(wù)列表并等待每個(gè)任務(wù)完成。
這突出表明我們可以獲得 asyncio 程序中所有任務(wù)的集合,其中包括創(chuàng)建的任務(wù)以及代表程序入口點(diǎn)的任務(wù)。
main coroutine started
task 0 is running
task 1 is running
task 2 is running
task 3 is running
task 4 is running
task 5 is running
task 6 is running
task 7 is running
task 8 is running
task 9 is running
> Task-9, <coroutine object task_coroutine at 0x10e186e30>
> Task-2, <coroutine object task_coroutine at 0x10e184e40>
> Task-11, <coroutine object task_coroutine at 0x10e186f10>
> Task-7, <coroutine object task_coroutine at 0x10e186d50>
> Task-4, <coroutine object task_coroutine at 0x10e185700>
> Task-10, <coroutine object task_coroutine at 0x10e186ea0>
> Task-8, <coroutine object task_coroutine at 0x10e186dc0>
> Task-5, <coroutine object task_coroutine at 0x10e186ab0>
> Task-1, <coroutine object main at 0x10e1847b0>
> Task-3, <coroutine object task_coroutine at 0x10e184f90>
> Task-6, <coroutine object task_coroutine at 0x10e186ce0>
接下來(lái),我們將探討如何同時(shí)運(yùn)行多個(gè)協(xié)程。