繁体   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