tractor/docs/api/to_asyncio.rst

3.0 KiB

asyncio interop: tractor.to_asyncio

"Infected asyncio" mode: spawn an actor with start_actor(..., infect_asyncio=True) and its process runs trio as a guest on top of the asyncio loop — letting your trio task tree drive asyncio tasks in the same process while the rest of the actor tree stays pure trio. Each trio <-> asyncio task pair is linked with structured concurrency (SC) semantics: error or cancellation on either side tears down both, with the cause translated cross-loop.

See examples/infected_asyncio_echo_server.py for a complete worked example.

tractor.to_asyncio

Starting asyncio tasks from trio

open_channel_from

run_task

Note

open_channel_from mirrors the Portal.open_context() handshake: the asyncio side calls chan.started_nowait(value) and that value pops out as first on the trio side. run_task is the one-shot form — run a single asyncio-compatible coroutine fn and return its result to trio.

The inter-loop channel

LinkedTaskChannel

Note

The trio side uses the async API (LinkedTaskChannel.send / LinkedTaskChannel.receive); the asyncio side uses the loop-safe sync/await mix (LinkedTaskChannel.send_nowait / LinkedTaskChannel.get / LinkedTaskChannel.started_nowait).

Translated exception types

Cross-loop failures are re-raised on the other side as one of these explicit translation types, so you always know which loop actually died first:

tractor._exceptions.AsyncioCancelled

tractor._exceptions.AsyncioTaskExited

tractor._exceptions.TrioCancelled

tractor._exceptions.TrioTaskExited

AsyncioRuntimeTranslationError

Guest-mode entrypoint

run_as_asyncio_guest() is the runtime-internal entrypoint that boots trio in guest mode inside an infected actor — you get it implicitly via infect_asyncio=True and shouldn't need to call it yourself.

/api/core for the infect_asyncio spawn flag, tractor.Actor.is_infected_aio for runtime introspection, /api/devx for using the debugger from inside asyncio tasks, and /guide/asyncio for the guided tour.