2.16. Utilities#
2.16.1. select
#
In some cases, you should wait for only one of multiple tasks. select
waits first passed awaitable object and returns the list of results.
import asyncio
import aiomisc
async def main():
loop = asyncio.get_event_loop()
event = asyncio.Event()
future = asyncio.Future()
loop.call_soon(event.set)
await aiomisc.select(event.wait(), future)
print(event.is_set()) # True
event = asyncio.Event()
future = asyncio.Future()
loop.call_soon(future.set_result, True)
results = await aiomisc.select(future, event.wait())
future_result, event_result = results
print(results.result()) # True
print(results.result_idx) # 0
print(event_result, future_result) # None, True
with aiomisc.entrypoint() as loop:
loop.run_until_complete(main())
Warning
When you don’t want to cancel pending tasks pass cancel=False
argument.
In this case, you have to handle task completion manually or get warnings.
2.16.2. cancel_tasks
#
All passed tasks will be canceled and the task will be returned:
import asyncio
from aiomisc import cancel_tasks
async def main():
done, pending = await asyncio.wait([
asyncio.sleep(i) for i in range(10)
], timeout=5)
print("Done", len(done), "tasks")
print("Pending", len(pending), "tasks")
await cancel_tasks(pending)
asyncio.run(main())
2.16.3. awaitable
#
Decorator wraps function and returns a function that returns awaitable object.
In case a function returns a future, the original future will be returned.
In case then the function returns a coroutine, the original coroutine will
be returned. In case than function returns a non-awaitable object, it’s will
be wrapped to a new coroutine that just returns this object. It’s useful
when you don’t want to check function results before
use it in await
expression.
import asyncio
import aiomisc
async def do_callback(func, *args):
awaitable_func = aiomisc.awaitable(func)
return await awaitable_func(*args)
print(asyncio.run(do_callback(asyncio.sleep, 2)))
print(asyncio.run(do_callback(lambda: 45)))
2.16.4. bind_socket
#
Bind socket and set setblocking(False)
for just created socket.
This detects address
format and selects the socket family automatically.
from aiomisc import bind_socket
# IPv4 socket
sock = bind_socket(address="127.0.0.1", port=1234)
# IPv6 socket (on Linux IPv4 socket will be bind too)
sock = bind_socket(address="::1", port=1234)
2.16.5. RecurringCallback
#
Runs coroutine function periodically with user-defined strategy.
from typing import Union
from aiomisc import new_event_loop, RecurringCallback
async def callback():
print("Hello")
FIRST_CALL = False
async def strategy(_: RecurringCallback) -> Union[int, float]:
global FIRST_CALL
if not FIRST_CALL:
FIRST_CALL = True
# Delay 5 second if just started
return 5
# Delay 10 seconds if it is not a first call
return 10
if __name__ == '__main__':
loop = new_event_loop()
periodic = RecurringCallback(callback)
task = periodic.start(strategy)
loop.run_forever()
The main purpose is this class is to provide ability to specify the asynchronous strategy function, which can be written very flexible.
Also, with the special exceptions, you can control the behavior of the started
RecurringCallback
.
from aiomisc import (
new_event_loop, RecurringCallback, StrategySkip, StrategyStop
)
async def strategy(_: RecurringCallback) -> Union[int, float]:
...
# Skip this attempt and wait 10 seconds
raise StrategySkip(10)
...
# Stop execution
raise StrategyStop()
if the strategy function returns an incorrect value (not a number), or does not raise special exceptions, the recurring execution is terminated.
2.16.6. PeriodicCallback
#
Runs coroutine function periodically with an optional delay of the first
execution. Uses RecurringCallback
under the hood.
import asyncio
import time
from aiomisc import new_event_loop, PeriodicCallback
async def periodic_function():
print("Hello")
if __name__ == '__main__':
loop = new_event_loop()
periodic = PeriodicCallback(periodic_function)
# Wait 10 seconds and call it each second after that
periodic.start(1, delay=10)
loop.run_forever()
2.16.7. CronCallback
#
Warning
You have to install croniter
package for use this feature:
pip install croniter
Or add extras when installing aiomisc:
pip install aiomisc[cron]
Runs coroutine function with cron scheduling execution.
Uses RecurringCallback
under the hood.
import asyncio
import time
from aiomisc import new_event_loop, CronCallback
async def cron_function():
print("Hello")
if __name__ == '__main__':
loop = new_event_loop()
periodic = CronCallback(cron_function)
# call it each second after that
periodic.start(spec="* * * * * *")
loop.run_forever()