Notes#
I/O in AsyncKivy#
asynckivy
does not have any I/O primitives unlike trio
and asyncio
do,
thus threads may be the best way to perform them without blocking the main-thread:
from concurrent.futures import ThreadPoolExecutor
import asynckivy as ak
executor = ThreadPoolExecutor()
def thread_blocking_operation():
'''
This function is called from outside the main-thread so you should not
perform any graphics-related operations here.
'''
async def async_fn():
r = await ak.run_in_thread(thread_blocking_operation)
print("return value:", r)
r = await ak.run_in_executor(executor, thread_blocking_operation)
print("return value:", r)
Unhandled exceptions (not BaseException
) are propagated to the caller so you can catch them like you do in
synchronous code:
import requests
import asynckivy as ak
async def async_fn(label):
try:
response = await ak.run_in_thread(lambda: requests.get('htt...', timeout=10))
except requests.Timeout:
label.text = "TIMEOUT!"
else:
label.text = "RECEIVED"
Kivy’s Event System#
(under construction)
The Problem with Async Generators#
asyncio
and trio
do some hacky stuff, sys.set_asyncgen_hooks()
and sys.get_asyncgen_hooks()
,
which likely hinders asynckivy-flavored async generators.
You can see its details here.
Because of that, the APIs that create async generators might not work perfectly if asyncio
or trio
is running.
Here is a list of them:
asynckivy.anim_with_xxx
Places where async operations are disallowed#
Most of the asynckivy APIs that return an async iterator don’t allow to perform async operations during the iteration. Here is a list of them:
asynckivy.anim_with_xxx
async for __ in rest_of_touch_events(...):
await awaitable # NOT ALLOWED
async with async_context_manager: # NOT ALLOWED
...
async for __ in async_iterator: # NOT ALLOWED
...
Animations may not end in time#
All the animation-related APIs don’t guarantee that they will end in time.
It probably doesn’t matter as long as the step
parameter is small enough.
However, in case it’s not, be aware of what might happen.
async for dt, et, p in anim_with_dt_et_ratio(duration=2.0, step=0.6):
print(dt, et, p)
dt |
et |
p |
---|---|---|
0.6 |
0.6 |
0.3 |
0.6 |
1.2 |
0.6 |
0.6 |
1.8 |
0.9 |
0.6 |
2.4 |
1.2 |
Look at the bottom row. et
largely exceeds the duration
and p
largely exceeds 1.0.
If you really want it to end in time, consider wrapping it in asynckivy.move_on_after()
.
async with move_on_after(2.0):
async for dt, et, p in anim_with_dt_et_progress(duration=2.0, step=0.6):
print(dt, et, p)
dt |
et |
p |
---|---|---|
0.6 |
0.6 |
0.3 |
0.6 |
1.2 |
0.6 |
0.6 |
1.8 |
0.9 |