I have the following code:
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
Normally, I would execute:
display = displayName('Tom',5)
loop = asyncio.get_event_loop()
loop.create_task(display.start())
and if I wanted to change the name being displayed I would execute:
loop.create_task(display.update_name('Jerry'))
and to stop the loop I would execute:
loop.create_task(display.stop())
which changes display.exit to True and ends the loop.
However, if I attempt to execute this code using:
asyncio.run(display.start())
then I cannot get the loop to close!
I've tried:
loop1 = asyncio.get_running_loop()
loop1.close()
and this did nothing. I can do a keyboard interrupt, but any time I try to run another task with asyncio.run(), I get an error message saying that asyncio.run() cannot be called from a running event loop!
How do I close this active loop so that I can use asyncio.run() again??!!!
I am working in a Jupyter Notebook, if this is relevant.
I scoured the internet and I found the following hack that seems to work:
import nest_asyncio
nest_asyncio.apply()
When I run this code it seems to cause Python to "forget" all the earlier asyncio.run() commands, and now I can use asyncio.run() to run other blocks of code as normal.
Your class has no errors. The error is the way you're using run()
method.
When you execute asyncio.run(display.start())
the program will wait to that coroutine to finish. So, in this case you're runing display.start()
that is an infinite loop. That's the reason why can't do anything else while that coroutine runs.
You have to call in asyncio.run()
a coroutine that manages all the instructions. See the code below:
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")
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
The solution you gave works, but it's not at all the recommended way to do it
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.