IqbalHamid
IqbalHamid

Reputation: 2532

await asyncio.sleep(1) not working in python

My code execution does not reach the print statement: print("I want to display after MyClass has started")

Why is this? I thought the purpose of await asyncio.sleep() is to unblock execution of code so that subsequent lines of code can run. Is that not the case?

import asyncio

class MyClass:
    def __init__(self):
        self.input = False
        asyncio.run(self.start())
        
        print("I want to display after MyClass has started")  #This line is never reached.
        
        
    async def start(self):
        while True:
            print("Changing state...")
            if self.input:
                print("I am on.")
                break
            await asyncio.sleep(1)

m = MyClass()
m.input = True  #This line is never reached!  Why?
print("I want to display after MyClass is started")

When I execute, it keeps printing "Changing state...". Even when I ctrl+c to quit, the execution continues as shown below. How can I properly terminate the execution? Sorry, I am new to python.

enter image description here

EDIT: I appreciate the common use of asyncio is for running two or more separate functions asynchronously. However, my class is one which will be responding to changes in its state. For example, I intend to write code in the setters to do stuff when the class objects attributes change -WHILE still having a while True event loop running in the background. Is there not any way to permit this? I have tried running the event loop in it's own thread. However, that thread then dominates and the class objects response times run into several seconds. This may be due to the GIL (Global Interpreter Lock) which we can do nothing about. I have also tried using multiprocessing, but then I lose access to the properties and methods of the object as parallel process run in their own memory spaces.

Upvotes: -1

Views: 1401

Answers (1)

Alon Gadot
Alon Gadot

Reputation: 565

In the init method of MyClass you invoke asyncio.run() - this method will execute the required routine until that routine terminates. In your case, since the main method includes a while True loop, it will never terminate.

Here is a slight modification of your code that perhaps shows the concurrency effect you're after -

import asyncio
class MyClass:
def __init__(self):
    self.input = False
    asyncio.run(self.main())

    print("I want to display after MyClass has been initialized.")  # This line is never reached.

async def main(self):
    work1 = self.work1()
    work2 = self.work2()
    await asyncio.gather(work1, work2)

async def work1(self):
    for idx in range(5):
        print('doing some work 1...')
        await asyncio.sleep(1)

async def work2(self):
    for idx in range(5):
        print('doing some work 2...')
        await asyncio.sleep(1)
m = MyClass()
print("I want to display after MyClass is terminated")

Upvotes: 2

Related Questions