EDITED TO ADD A WORKING PROGRAM
To make your program work you need to deal with several issues.
- You need a non-blocking means of obtaining input from the user.
- You need to use asyncio.sleep() instead of time.sleep()
- Instead of awaiting the cooldown function, you need to create it as a task so it can run in parallel to main().
- You need to add sleep calls to main so your cooldown task gets an opportunity to run.
To deal with #1 I replaced your input function with calls to kbhit and getch, both functions from msvcrt (Microsoft Visual C runtime). So this program will only run on windows. So user inputs are just one character. The letter "t" means the same as "test" in your program.
I removed both of your global variables, which were unnecessary.
If there is no input from the user, main() sleeps for 0.1 second.
If the user strikes the "t" key 3 times, main() creates a task, which runs as soon as main() reaches its next await statement.
To see if the task is finished, call its "done" method. You do not need a global variable to pass around this information.
Otherwise the logic is similar to yours and so are the print statements. The program works fine with Python3.8 and Windows10.
I found the documentation for asyncio to be extremely confusing, and it took me a long time to figure out the basics. What seems to be missing is an introduction that explains the basic concepts. Once you get past that it all works beautifully but the learning curve is steeper than it needs to be.
# python3.8
from msvcrt import kbhit, getch
import asyncio
import time
async def main():
count = 0
task = None
print("Hit a key to make things happen")
while True:
if kbhit():
c = str(getch(), encoding='utf-8')
print("Key pressed", c, count)
else:
await asyncio.sleep(0.1)
continue
if c == "t":
count += 1
print("did test: " + str(count) + " times.")
if count >= 3:
if task is None or task.done():
task = asyncio.create_task(cooldown())
if task is not None and not task.done():
print("Cooling")
async def cooldown():
print("Cooldown is activated.")
await asyncio.sleep(3.0)
print("Cooldown is deactivated.")
if __name__ == "__main__":
asyncio.run(main())
ORIGINAL ANSWER:
Change from time.sleep to asyncio.sleep and await on it:
async def cooldown():
global cool
cool = 1
print("Cooldown is activated.")
await asyncio.sleep(3)
cool = 0
print("Cooldown is deactivated.")
time.sleep() blocks the current thread. asyncio.sleep is awaitable, so when you await on it the thread is not blocked. Other tasks can run.
I also see that you await cooldown() in your main coroutine. The main coroutine will not continue until cooldown is finished. Is that what you want? Perhaps it would be better to replace the await cooldown() with this:
asyncio.create_task(cooldown())
In that case your main() function will proceed. But you won't see the print statement at the end of cooldown() because there is no await expression in main(). To deal with that, put the line
await asyncio.sleep(0)
somewhere in your loop. That will allow the event loop to switch tasks and you will see the print statement.
Be aware that the input() statement is blocking, and when your main() function calls input, none of your coroutines can proceed until you type something.