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.