Running aioschedule with other coroutine in python - python

I have two coroutines one of which is using aioschedule. This is my code
import aioschedule as schedule
import asyncio
async def foo():
while True:
print('foooooo')
await asyncio.sleep(5)
async def bar():
while True:
print('bar')
await asyncio.sleep(1)
schedule.every(2).seconds.do(bar)
loop = asyncio.get_event_loop()
loop.create_task(schedule.run_pending())
loop.create_task(foo())
try:
loop.run_forever()
except KeyboardInterrupt:
loop.stop()
What i want is it should printed bar every n seconds when other task is running but the output is only foooooo. Am i missing something?

try this:
import aioschedule as schedule
import asyncio
async def foo():
while True:
print('foooooo')
await asyncio.sleep(5)
async def bar():
while True:
print('bar')
await asyncio.sleep(1)
#schedule.every(2).seconds.do(bar) <---removed line
loop = asyncio.get_event_loop()
loop.create_task(schedule.run_pending())
loop.create_task(foo())
loop.create_task(bar()) #<---- added line
try:
loop.run_forever()
except KeyboardInterrupt:
loop.stop()

Related

Pause all asyncio tasks in Python

I have some asyncio tasks and I need to pause all of them.
This is my part of code:
import asyncio
import random
async def workers1():
while True:
k = random.randint(100, 200)
await asyncio.sleep(k)
await my_print(k)
async def workers2():
while True:
k = random.randint(100, 200)
await asyncio.sleep(k)
await my_print(k)
async def my_print(k):
print(k)
if k == 122:
>>>>>>> suspend all of workers
while k != 155:
k = await repair()
await asyncio.sleep(1)
r>>>>>> resume all of workers
async def main():
tasks = [asyncio.create_task(workers1()),
asyncio.create_task(workers2())
]
[await x for x in tasks]
if __name__ == '__main__':
asyncio.run(main())
How can I suspend all of workers in my code when trouble happens in a function my_print and after repair in my_print resume all of tasks?
I will be glad if you give an example.
I have been seen this link. But that's not what I need.
Simply replace your call to await asyncio.sleep(1) with time.sleep(1). If your code doesn't have an await expression in it, all the other tasks are effectively blocked.
import asyncio
import random
import time
async def workers1():
while True:
k = random.randint(100, 200)
await asyncio.sleep(k)
await my_print(k)
async def workers2():
while True:
k = random.randint(100, 200)
await asyncio.sleep(k)
await my_print(k)
async def my_print(k):
print(k)
if k == 122:
>>>>>>> suspend all of workers
while k != 155:
k = random.randint(100, 200)
time.sleep(1.0) # CHANGE HERE
r>>>>>> resume all of workers
async def main():
tasks = [asyncio.create_task(workers1()),
asyncio.create_task(workers2())
]
[await x for x in tasks]
if __name__ == '__main__':
asyncio.run(main())
So, first, note that the time.sleep trick can be replaced with any non-asynchronous code. So you can do anything that runs synchronously instead of time.sleep.
Including set up a second asyncio loop in a different thread and run tasks in that loop.
The following code uses ThreadPoolExecutor from concurrent.futures to set up a new event loop. In particular:
future = executor.submit(asyncio.run, task_3())
Will set up a new thread and run task_3 in that new loop.
The next line future.result() blocks the entire first loop (task_1 and task_2) until task_3 exits.
In task_3 you can do any asyncio operations you like, and until that exits all of the existing tasks will be suspended.
import asyncio, concurrent.futures
async def task_1():
while True:
print('task 1 runs')
await asyncio.sleep(1)
async def task_2():
print('task 2 starts')
await asyncio.sleep(5)
print('first set of tasks suspends')
future = executor.submit(asyncio.run, task_3())
print('suspending existing tasks')
future.result()
print('resuming tasks')
async def task_3():
print('task 3 runs')
await asyncio.sleep(4)
print('task 3 finishes')
async def main():
asyncio.ensure_future(task_1())
asyncio.ensure_future(task_2())
await asyncio.sleep(15)
executor = concurrent.futures.ThreadPoolExecutor()
asyncio.run(main())

Cannot keyboard interrupt trio/asyncio program (ctrl+c) to exit

The following code works, but fails to exit upon CTRL+c
Can anyone explain why, and how to fix?
It's asyncio code, but I'm using trio-asyncio (forward planning) to allow me to also use trio code.
#!.venv/bin/python
import asyncio
import trio
import trio_asyncio
from binance import AsyncClient, BinanceSocketManager
as_trio = trio_asyncio.aio_as_trio
as_aio = trio_asyncio.trio_as_aio
from contextlib import asynccontextmanager
#asynccontextmanager
async def AClient():
client = await AsyncClient.create()
try:
yield client
except KeyboardInterrupt:
print('ctrl+c')
exit(0)
finally:
await client.close_connection()
async def kline_listener(client):
print(1)
bm = BinanceSocketManager(client)
async with bm.kline_socket(symbol='BNBBTC') as stream:
while True:
try:
res = await stream.recv()
print(res)
except KeyboardInterrupt:
break
#as_trio
async def aio_main():
async with AClient() as client:
exchange_info = await client.get_exchange_info()
tickers = await client.get_all_tickers()
print(client, exchange_info.keys(), tickers[:2])
kline = asyncio.create_task(kline_listener(client))
await kline
if __name__ == "__main__":
trio_asyncio.run(aio_main)
I've placed except KeyboardInterrupt at 2 places, though it appears to do nothing.

Python async call_later in while loop

I have a function that I want to call every minute for instance and my code look like this:
async def fun1():
print('fun1')
await asyncio.sleep(30)
async def fun2():
print('fun2')
await asyncio.sleep(10)
async def fun3():
print('fun3')
async def main():
global loop
loop.create_task(fun1())
loop.create_task(fun2())
while True:
await fun3()
await asyncio.sleep(1)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
but it does not print anything. I would like my function to be called every 10 seconds for instance. It looks like fun2 is waiting for fun1 to finish instead of triggering every 30 seconds and 10 seconds respectively...
Any idea why pelase?
Currently, fun1 and fun2 will only print once each since neither contain a loop. Add a loop to make them each print every 10/30 seconds.
import asyncio
async def fun1():
while True:
print('fun1')
await asyncio.sleep(30)
async def fun2():
while True:
print('fun2')
await asyncio.sleep(10)
async def fun3():
print('fun3')
async def main():
global loop
loop.create_task(fun1())
loop.create_task(fun2())
while True:
await fun3()
await asyncio.sleep(1)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

How to run two task concurrently with Python async/await?

Code:
import asyncio
async def f1():
print('f1:1')
await asyncio.sleep(2)
print('f1:2')
async def f2():
print('f2:1')
await asyncio.sleep(2)
print('f2:2')
async def f():
await f1()
await f2()
asyncio.run(f())
Result:
f1:1
f1:2
f2:1
f2:2
What I expected is run f1 and f2 concurrently, and with result:
f1:1
f2:1
f1:2
f2:2
So could anyone please give me some suggestion?
Use gather():
import asyncio
async def f1():
print('f1:1')
await asyncio.sleep(2)
print('f1:2')
async def f2():
print('f2:1')
await asyncio.sleep(2)
print('f2:2')
async def f():
await asyncio.gather(f1(), f2())
asyncio.run(f())

Asyncio task cancellation

This is a test script I created to better understand task cancellation -
import asyncio
import random
import signal
import traceback
async def shutdown(signame, loop):
print("Shutting down")
tasks = [task for task in asyncio.Task.all_tasks()]
for task in tasks:
task.cancel()
try:
await task
except asyncio.CancelledError:
print("Task cancelled: %s", task)
loop.stop()
async def another():
await asyncio.sleep(2)
async def some_other_process():
await asyncio.sleep(5)
return "Me"
async def process(job, loop, i):
print(i)
task = loop.create_task(some_other_process())
value = await task
if i < 1:
another_task = loop.create_task(another())
await another_task
# await some_other_process()
def pull(loop):
i = 0
while True:
job = f"random-integer-{random.randint(0, 100)}"
try:
loop.run_until_complete(process(job, loop, i))
i += 1
except asyncio.CancelledError as e:
print("Task cancelled")
break
except Exception:
print(traceback.format_exc())
# asyncio.get_event_loop().stop()
def main():
try:
loop = asyncio.get_event_loop()
for signame in ['SIGINT']:
loop.add_signal_handler(
getattr(signal, signame),
lambda: asyncio.ensure_future(shutdown(signame, loop))
)
try:
pull(loop)
except Exception:
print(traceback.format_exc())
finally:
loop.close()
finally:
print("Done")
if __name__ == "__main__":
main()
And I can not understand why I see -
Task was destroyed but it is pending!
task: <Task cancelling coro=<shutdown() done, defined at test.py:6>>
loop.add_signal_handler(
getattr(signal, signame),
lambda: asyncio.ensure_future(shutdown(signame, loop))
)
Here using asyncio.ensure_future you create task for shutdown coroutine, but you don't await anywhere for this task to be finished. Later when you close event loop it warns you this task is pending.
Upd:
If you want to do some clenup, the best place for it is right before loop.close() regardless of reason your script ended (signal, exception, etc.)
Try to alter your code this way:
# ...
async def shutdown(loop): # remove `signal` arg
# ...
def main():
try:
loop = asyncio.get_event_loop()
try:
pull(loop)
except Exception:
print(traceback.format_exc())
finally:
loop.run_until_complete(shutdown(loop)) # just run until shutdown is done
loop.close()
finally:
print("Done")
# ...
Upd2:
In case you still want signal handler, you probably want to do something like this:
from functools import partial
loop.add_signal_handler(
getattr(signal, signame),
partial(cb, signame, loop)
)
def cb(signame, loop):
loop.stop()
loop.run_until_complete(shutdown(signame, loop))

Categories

Resources