How to use python async task without await - python

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

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()

Preferred method to keep long-running client alive in Python asyncio

I'd like to keep a client app running that uses async.run to start its main function:
async def main():
nc = await nats.connect(nats_url)
js = nc.jetstream()
await js.add_stream(name=stream, subjects=[subject])
await js.subscribe(subject, qgroup, cb=do_work)
if __name__ == "__main__":
asyncio.run(main())
Running as above, of course, the program completes immediately. What's the preferred way to keep a client running using asyncio?
After looking at the Python asyncio docs, the closest example i found is this:
Note the asyncio.sleep inside a loop, similar to the traditional pattern of an infinite loop around a blocking function.
async def main():
nc = await nats.connect(nats_url)
js = nc.jetstream()
await js.add_stream(name=stream, subjects=[subject])
await js.subscribe(subject, qgroup, cb=do_work)
while True:
print("loop")
await asyncio.sleep(10)
if __name__ == "__main__":
asyncio.run(main())
I don't know js but for a regular nats client instead of
while True:
print("loop")
await asyncio.sleep(10)
you should add
nc.wait(count=1000)
for getting 1000 messages, or
while True:
print('got a new message:')
nc.wait(count=1)
for running forever

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())

Add multithreading layer to Asyncio

I currently have this piece of code running just fine using AsyncIO.
async def main():
while(1):
loop.create_task(startAsyncJob())
await asyncio.sleep(1)
async def startAsyncJob():
#myCodeHere
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
I tried to add a multithreading layer so I can run concurrently multiple pieces of what inside my "main". So I extracted its code, put it in its own function AsyncJobThread that I launch through my new main function using threads:
def main():
try:
_thread.start_new_thread( AsyncJobThread, (1))
_thread.start_new_thread( AsyncJobThread, (15))
except:
print ("Error: unable to start thread")
async def AsyncJobThread(frequence):
while(1):
loop.create_task(startAsyncJob())
await asyncio.sleep(frequence)
async def startAsyncJob():
#myCodeHere
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
However the current implementation gives me the following error:
sys:1: RuntimeWarning: coroutine 'AsyncJobThread' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
As requested, here's your code modified to use asyncio.gather.
async def main():
await asyncio.gather(
AsyncJobThread(1),
AsyncJobThread(15),
)
async def AsyncJobThread(frequence):
loop = asyncio.get_event_loop()
while True:
loop.create_task(startAsyncJob())
await asyncio.sleep(frequence)
async def startAsyncJob():
#myCodeHere
asyncio.run(main())
You could also get a reference to the loop and pass it into AsyncJobThread if you prefer.

How to make async code run on startup - 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.

Categories