簡體   English   中英

如何在沒有名稱的異步中停止無限事件循環?

[英]How to stop an infinite event loop in asyncio with no name?

我有以下代碼:

import asyncio
import time

class displayName:
    def __init__(self, name, delay, exit = False):
        self.name = name
        self.delay = delay
        self.exit = exit
    async def start(self):
        #displays name of object at regular time intervals
        self.exit = False
        print('starting display program...')
        while True:
            if self.exit == True:
                print('ending display program')
                break
            print(self.name)
            await asyncio.sleep(self.delay)
    async def stop(self):
        await asyncio.sleep(0)
        self.exit = True
    async def update_name(self, name):
        await asyncio.sleep(0)
        self.name = name
    async def update_delay(self, delay):
        await asyncio.sleep(0)
        self.delay = delay

通常,我會執行:

display = displayName('Tom',5)
loop = asyncio.get_event_loop()
loop.create_task(display.start())

如果我想更改顯示的名稱,我會執行:

loop.create_task(display.update_name('Jerry'))

並停止循環我會執行:

loop.create_task(display.stop())

它將 display.exit 更改為 True 並結束循環。

但是,如果我嘗試使用以下方法執行此代碼:

asyncio.run(display.start())

那么我無法關閉循環!

我試過了:

loop1 = asyncio.get_running_loop()
loop1.close()

這什么也沒做。 我可以進行鍵盤中斷,但是每當我嘗試使用 asyncio.run() 運行另一個任務時,我都會收到一條錯誤消息,指出無法從正在運行的事件循環中調用 asyncio.run()!

如何關閉這個活動循環,以便我可以再次使用 asyncio.run() ??!!!

如果這是相關的,我正在使用 Jupyter Notebook。

我搜索了互聯網,發現以下似乎可行的技巧:

import nest_asyncio
nest_asyncio.apply()

當我運行此代碼時,它似乎導致 Python “忘記”所有早期的 asyncio.run() 命令,現在我可以使用 asyncio.run() 正常運行其他代碼塊。

您的 class 沒有錯誤。 錯誤是您使用run()方法的方式。

當您執行asyncio.run(display.start())時,程序將等待該協程完成。 因此,在這種情況下,您正在運行display.start()這是一個無限循環。 這就是為什么協程運行時不能做任何其他事情的原因。

您必須在asyncio.run()中調用一個管理所有指令的協程。 請看下面的代碼:

import asyncio

class displayName:
    def __init__(self, name, delay, exit = False):
        self.name = name
        self.delay = delay
        self.exit = exit
    async def start(self):
        #displays name of object at regular time intervals
        self.exit = False
        print('starting display program...')
        while True:
            if self.exit == True:
                print('ending display program')
                break
            print(f'name: {self.name}     delay:{self.delay}')
            await asyncio.sleep(self.delay)
    async def stop(self):
        await asyncio.sleep(0)
        self.exit = True
    async def update_name(self, name):
        await asyncio.sleep(0)
        self.name = name
    async def update_delay(self, delay):
        await asyncio.sleep(0)
        self.delay = delay

async def main():
    x = displayName('Tom', 1) #Create an instance of displayName
    task = asyncio.create_task(x.start()) #Run x.start()
    await asyncio.sleep(3) #waits 3 secs
    await x.update_name('Chris') #Change name
    await asyncio.sleep(3) #waits 3 secs
    await x.update_delay(0.5) #Change delay time
    await asyncio.sleep(3) #waits 3 secs
    await x.stop() #Stop task
    await task #Wait for task to end

asyncio.run(main())
print("This sentence will NOT be executed concurrently...")
print("This will be executed once asyncio.run() is done")

Output:

name: Tom     delay:1
name: Tom     delay:1
name: Tom     delay:1
name: Tom     delay:1
name: Chris     delay:1
name: Chris     delay:1
name: Chris     delay:1
name: Chris     delay:0.5
name: Chris     delay:0.5
name: Chris     delay:0.5
name: Chris     delay:0.5
ending display program
This sentence will NOT be executed concurrently...
This will be executed once asyncio.run() is done

您提供的解決方案有效,但這根本不是推薦的方法

暫無
暫無

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

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