Spawn a "system" task. System tasks have a few differences from regular tasks: * They don't need an explicit nursery; instead they go into the internal "system nursery". * If a system task raises an exception, then it's converted into a :exc:`~trio.Trio
(
self,
async_fn: Callable[[Unpack[PosArgT]], Awaitable[object]],
*args: Unpack[PosArgT],
name: object = None,
context: contextvars.Context | None = None,
)
| 2084 | |
| 2085 | @_public |
| 2086 | def spawn_system_task( |
| 2087 | self, |
| 2088 | async_fn: Callable[[Unpack[PosArgT]], Awaitable[object]], |
| 2089 | *args: Unpack[PosArgT], |
| 2090 | name: object = None, |
| 2091 | context: contextvars.Context | None = None, |
| 2092 | ) -> Task: |
| 2093 | """Spawn a "system" task. |
| 2094 | |
| 2095 | System tasks have a few differences from regular tasks: |
| 2096 | |
| 2097 | * They don't need an explicit nursery; instead they go into the |
| 2098 | internal "system nursery". |
| 2099 | |
| 2100 | * If a system task raises an exception, then it's converted into a |
| 2101 | :exc:`~trio.TrioInternalError` and *all* tasks are cancelled. If you |
| 2102 | write a system task, you should be careful to make sure it doesn't |
| 2103 | crash. |
| 2104 | |
| 2105 | * System tasks are automatically cancelled when the main task exits. |
| 2106 | |
| 2107 | * By default, system tasks have :exc:`KeyboardInterrupt` protection |
| 2108 | *enabled*. If you want your task to be interruptible by control-C, |
| 2109 | then you need to use :func:`disable_ki_protection` explicitly (and |
| 2110 | come up with some plan for what to do with a |
| 2111 | :exc:`KeyboardInterrupt`, given that system tasks aren't allowed to |
| 2112 | raise exceptions). |
| 2113 | |
| 2114 | * System tasks do not inherit context variables from their creator. |
| 2115 | |
| 2116 | Towards the end of a call to :meth:`trio.run`, after the main |
| 2117 | task and all system tasks have exited, the system nursery |
| 2118 | becomes closed. At this point, new calls to |
| 2119 | :func:`spawn_system_task` will raise ``RuntimeError("Nursery |
| 2120 | is closed to new arrivals")`` instead of creating a system |
| 2121 | task. It's possible to encounter this state either in |
| 2122 | a ``finally`` block in an async generator, or in a callback |
| 2123 | passed to :meth:`TrioToken.run_sync_soon` at the right moment. |
| 2124 | |
| 2125 | Args: |
| 2126 | async_fn: An async callable. |
| 2127 | args: Positional arguments for ``async_fn``. If you want to pass |
| 2128 | keyword arguments, use :func:`functools.partial`. |
| 2129 | name: The name for this task. Only used for debugging/introspection |
| 2130 | (e.g. ``repr(task_obj)``). If this isn't a string, |
| 2131 | :func:`spawn_system_task` will try to make it one. A common use |
| 2132 | case is if you're wrapping a function before spawning a new |
| 2133 | task, you might pass the original function as the ``name=`` to |
| 2134 | make debugging easier. |
| 2135 | context: An optional ``contextvars.Context`` object with context variables |
| 2136 | to use for this task. You would normally get a copy of the current |
| 2137 | context with ``context = contextvars.copy_context()`` and then you would |
| 2138 | pass that ``context`` object here. |
| 2139 | |
| 2140 | Returns: |
| 2141 | Task: the newly spawned task |
| 2142 | |
| 2143 | """ |