簡體   English   中英

asyncio create_task 永遠運行

[英]asyncio create_task to run forever

我有以下代碼

import asyncio

loop = asyncio.get_event_loop()

async def while_loop():
    n = 0
    while True:
        print(f"{n}")
        await asyncio.sleep(2)
        n = n+1

async def some_func():
    await asyncio.sleep(5)
    print("Some Func")

future = loop.create_task(while_loop())
loop.run_until_complete(some_func())

我希望while_loop函數永遠運行,但它似乎只是作為調用run_until_complete的結果而執行,並且一旦some_func完成執行,它就會停止打印 while 循環。 我看到的輸出是:

0
1
2
Some Func

我希望即使在some_func完成后這些數字也會繼續打印。

0
1
2
Some Func
3
4
5
6
.
.
.

打印更多數字的唯一方法是再次調用some_func

我希望即使在some_func完成后這些數字也會繼續打印。

run_until_complete的參數控制事件循環運行的時間。 一旦事件循環停止運行,所有協程都會有效地暫停,而不僅僅是您一直在等待的協程。 但是您確實有不同的選擇:

  • loop.run_until_complete(some_func()) - 你已經使用過的; 運行事件循環,直到some_func協程完成。 在此期間也並行執行其他協程,但也會在事件循環完成后立即停止執行它們。

  • loop.run_forever() - 運行事件循環,直到某個協程或回調調用loop.stop() 如果他們都沒有這樣做,那么即使所有協程都結束了,事件循環也不會停止。 在你的情況下,你會調用loop.create_task(while_loop())然后是loop.create_task(some_func()) ,然后是loop.run_forever()

  • loop.run_until_complete(asyncio.gather(while_loop(), some_func()))直到兩個指定的協程完成運行事件循環。 這(等待所有任務)顯然是您期望loop.run_until_complete()自動執行的操作,即使您只指定一個,但它不會像那樣工作,它會在指定的協程完成后立即停止。 asyncio.gather可用於一次等待多個協程。 有關等待的更微調控制,另請參閱asyncio.wait

由於您的協程之一永遠運行,最后兩個選項將是等效的,並會產生預期的輸出。

這是我用來async with上下文保持async with永遠活着的方法:

def never():
    try:
        return never.never
    except AttributeError:
        never.never = asyncio.Future()
        return never.never


async def create_context_and_dependent_tasks():
    async with create_ctx() as ctx:
        for i in range(10):
            asyncio.create_task(use_ctx_indefinitely(bar))

        await never()   # **THIS** is the main idea I wanted to talk about.

它不適用於多個循環,但這很少是一種情況(並且可以通過對never函數進行輕微修改來解決):

def never():
    loop = asyncio.get_running_loop()
    try:
        return never.nevers[loop]
    except KeyError:
        never.nevers[loop] = asyncio.Future()
    return never.nevers[loop]


never.nevers = {}

問題是,如果您創建了本地未來:

async def foo():
    never = asyncio.Future()
    await never

它會被垃圾收集,任務會被銷毀……只是因為 Python 充滿了驚喜。 所以你必須在全局范圍內創建未來(但不是一開始,因為循環還不存在)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM