How to make async code run on startup - Python - python

Heyy,
how would I make my asynchronous code run on startup?
So this is the easiest example I could think of to make.
async def mainMenuCLI():
print("This is the CLI")
And I want the asynchronous mainMenuCLI to run on startup but I don't want it to take as many tasks because I'm not sure what is the max :(
I need it to be async because of async_input, discord.py and stuff, just don't tell me to make it sync, thanks!

If I understand your question... Do you need something likethis?
import asyncio
async def async_example():
print("hellooooo, I'm an async function")
async def main():
asyncio.Task(async_example())
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
You can add some tasks outside the async func if you need:
import asyncio
async def async_example():
print("hellooooo, I'm an async function")
await asyncio.sleep(1)
print("async function done")
async def main():
asyncio.Task(async_example())
print('This is before wait')
await asyncio.sleep(1)
print('This is after await')
await asyncio.sleep(1)
print('Ok, goodbye')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
*Note: if your py version is prior to 3.7, change asyncio.Task per asyncio.ensure_future.

Related

Python run 2 async infinite loops after the first one already started

I want to run 2 infinite async loops that should run simultanoesly.
However though, they are not called together.
The first loop starts running immediately and when it detects something it calls the second loop and they should run independently.
Something like this:
async def test():
while True:
print("test")
time.sleep(7)
async def call_test():
loopd = asyncio.get_running_loop()
task = loopd.create_task(test())
await task
async def print_main():
while True:
print("main")
await call_test()
time.sleep(5)
def main():
loop = asyncio.get_event_loop()
loop.create_task(print_main())
loop.run_forever()
if __name__ == '__main__':
main()
PS:
There are a lot of similar questions, but they all run 2 independent loops from the start.
You should not use time.sleep with asyncio loop in the same thread, otherwise time.sleep will block all other tasks of the asyncio loop.
You need only one asyncio loop in one thread, because only one loop can do work simultaneously in the same thread.
Your code will work with the following changes:
import asyncio
async def test():
while True:
print("test")
await asyncio.sleep(7)
async def print_main():
another_task = None
while True:
print("main")
if another_task is None:
another_task = asyncio.create_task(test())
await asyncio.sleep(5)
def main():
loop = asyncio.get_event_loop()
loop.create_task(print_main())
loop.run_forever()
if __name__ == '__main__':
main()

Asyncio sleep blocking coroutines

I have this code :
import asyncio
import aioconsole
async def imp():
print("Cool I'm printing")
await asyncio.sleep(2)
await imp()
async def console():
while True:
comm = await aioconsole.ainput(">>")
if 'cool' in comm:
await imp()
async def main():
console_use = asyncio.create_task(console())
await console_use
if __name__ == '__main__':
try:
asyncio.run(main())
except AttributeError:
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
The problem is that when the code enter to the function imp() the console() function stops working and I would like to continue using the console for other functions. How can I solve that?
Ps. I tried doing threads, create tasks and nothing is working...

How to poll with aiogram without the executor?

I am trying to use aiogram, but as a component of a larger application, most examples do the following call in the main after defining the callbacks>
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
What I am trying to implement is having the polling in a separate task which I can run concurrently with asyncio.gather() as shown below:
import asyncio
async def task1():
while True:
# Perform aiogram polling
await asyncio.sleep()
async def task2():
while True:
# Perform other application's component
await asyncio.sleep()
async def main():
await asyncio.gather(
task1(),
task2(),
)
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
I searched in the code for the executor class, yet it performs an startup sequence and then calls itself the loop.get_event_loop() and loop.run_forever(),
Does aiogram have a built-in method for performing this?
The solution was to use the dispatcher directly rather than the executor utility as shown below:
async def task1():
await dp.start_polling()
async def task2():
while True:
# Perform other application's component
await asyncio.sleep(1)
async def main():
await asyncio.gather(
task1(),
task2(),
)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())

How to use python async task without await

I use async create_task to run my task in background, but my_task() method not be executed.
async def my_task():
print("starting my task...")
time.sleep(2)
print("finished my task.")
if __name__ == '__main__':
print("1111")
loop = asyncio.get_event_loop()
loop.create_task(my_task())
print("2222")
the result is
1111
2222
There is a simple fix for this, but you still need to use await which you cannot avoid because create tasks returns a coroutine
import asyncio
async def my_task():
print("starting my task...")
await asyncio.sleep(2)
print("finished my task.")
if __name__ == '__main__':
print("1111")
loop = asyncio.get_event_loop()
loop.run_until_complete(my_task())
# or use can use asyncio.run(my_task())
print("2222")
EDIT: Made changes for pyfile, instead of notebook, thanks user4815162342 for pointing out

python Make an async timer without waiting to finish

I want to make a timer which is started in a normal function, but in the timer function, it should be able to call an async function
I want to do something like this:
startTimer()
while True:
print("e")
def startTimer(waitForSeconds: int):
# Wait for `waitForSeconds`
await myAsyncFunc()
async def myAsyncFunc():
print("in my async func")
Where the while True loop should do its stuff and after waitForSeconds the timer the async function should execute an other async function, but waiting shouldn't block any other actions and doesn't need to be awaited
If something isn't understandable, I'm sorry, I'll try to explain it then
Thanks
If you want to run your synchronous and asynchronous code in parallel, you will need to run one of them in a separate thread. For example:
def sync_code():
while True:
print("e")
async def start_timer(secs):
await asyncio.sleep(secs)
await async_func()
async def main():
asyncio.create_task(start_timer(1))
loop = asyncio.get_event_loop()
# use run_in_executor to run sync code in a separate thread
# while this thread runs the event loop
await loop.run_in_executor(None, sync_code)
asyncio.run(main())
If the above is not acceptable for you (e.g. because it turns the whole program into an asyncio program), you can also run the event loop in a background thread, and submit tasks to it using asyncio.run_coroutine_threadsafe. That approach would allow startTimer to have the signature (and interface) like you wanted it:
def startTimer(waitForSeconds):
loop = asyncio.new_event_loop()
threading.Thread(daemon=True, target=loop.run_forever).start()
async def sleep_and_run():
await asyncio.sleep(waitForSeconds)
await myAsyncFunc()
asyncio.run_coroutine_threadsafe(sleep_and_run(), loop)
async def myAsyncFunc():
print("in my async func")
startTimer(1)
while True:
print("e")
I'm pretty sure that you are familiar with concurent processing, but you didn't show exactly what you want. So if I understand you correctly you want to have 2 processes. First is doing only while True, and the second process is the timer(waits e.g. 5s) and it will call async task. I assume that you are using asyncio according to tags:
import asyncio
async def myAsyncFunc():
print("in my async func")
async def call_after(delay):
await asyncio.sleep(delay)
await myAsyncFunc()
async def while_true():
while True:
await asyncio.sleep(1) # sleep here to avoid to large output
print("e")
async def main():
task1 = asyncio.create_task(
while_true())
task2 = asyncio.create_task(
call_after(5))
# Wait until both tasks are completed (should take
# around 2 seconds.)
await task1
await task2
asyncio.run(main())

Categories