17db96d56Sopenharmony_ci.. currentmodule:: asyncio 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci.. _asyncio-policies: 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci======== 77db96d56Sopenharmony_ciPolicies 87db96d56Sopenharmony_ci======== 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ciAn event loop policy is a global object 117db96d56Sopenharmony_ciused to get and set the current :ref:`event loop <asyncio-event-loop>`, 127db96d56Sopenharmony_cias well as create new event loops. 137db96d56Sopenharmony_ciThe default policy can be :ref:`replaced <asyncio-policy-get-set>` with 147db96d56Sopenharmony_ci:ref:`built-in alternatives <asyncio-policy-builtin>` 157db96d56Sopenharmony_cito use different event loop implementations, 167db96d56Sopenharmony_cior substituted by a :ref:`custom policy <asyncio-custom-policies>` 177db96d56Sopenharmony_cithat can override these behaviors. 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ciThe :ref:`policy object <asyncio-policy-objects>` 207db96d56Sopenharmony_cigets and sets a separate event loop per *context*. 217db96d56Sopenharmony_ciThis is per-thread by default, 227db96d56Sopenharmony_cithough custom policies could define *context* differently. 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_ciCustom event loop policies can control the behavior of 257db96d56Sopenharmony_ci:func:`get_event_loop`, :func:`set_event_loop`, and :func:`new_event_loop`. 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ciPolicy objects should implement the APIs defined 287db96d56Sopenharmony_ciin the :class:`AbstractEventLoopPolicy` abstract base class. 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci.. _asyncio-policy-get-set: 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ciGetting and Setting the Policy 347db96d56Sopenharmony_ci============================== 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ciThe following functions can be used to get and set the policy 377db96d56Sopenharmony_cifor the current process: 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci.. function:: get_event_loop_policy() 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci Return the current process-wide policy. 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci.. function:: set_event_loop_policy(policy) 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_ci Set the current process-wide policy to *policy*. 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci If *policy* is set to ``None``, the default policy is restored. 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ci.. _asyncio-policy-objects: 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ciPolicy Objects 537db96d56Sopenharmony_ci============== 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ciThe abstract event loop policy base class is defined as follows: 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_ci.. class:: AbstractEventLoopPolicy 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci An abstract base class for asyncio policies. 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_ci .. method:: get_event_loop() 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci Get the event loop for the current context. 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci Return an event loop object implementing the 667db96d56Sopenharmony_ci :class:`AbstractEventLoop` interface. 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ci This method should never return ``None``. 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci .. versionchanged:: 3.6 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci .. method:: set_event_loop(loop) 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci Set the event loop for the current context to *loop*. 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci .. method:: new_event_loop() 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci Create and return a new event loop object. 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci This method should never return ``None``. 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ci .. method:: get_child_watcher() 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci Get a child process watcher object. 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci Return a watcher object implementing the 877db96d56Sopenharmony_ci :class:`AbstractChildWatcher` interface. 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci This function is Unix specific. 907db96d56Sopenharmony_ci 917db96d56Sopenharmony_ci .. method:: set_child_watcher(watcher) 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci Set the current child process watcher to *watcher*. 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ci This function is Unix specific. 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci.. _asyncio-policy-builtin: 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ciasyncio ships with the following built-in policies: 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci.. class:: DefaultEventLoopPolicy 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci The default asyncio policy. Uses :class:`SelectorEventLoop` 1067db96d56Sopenharmony_ci on Unix and :class:`ProactorEventLoop` on Windows. 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_ci There is no need to install the default policy manually. asyncio 1097db96d56Sopenharmony_ci is configured to use the default policy automatically. 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci .. versionchanged:: 3.8 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci On Windows, :class:`ProactorEventLoop` is now used by default. 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci .. note:: 1167db96d56Sopenharmony_ci In Python versions 3.10.9, 3.11.1 and 3.12 the :meth:`get_event_loop` 1177db96d56Sopenharmony_ci method of the default asyncio policy emits a :exc:`DeprecationWarning` 1187db96d56Sopenharmony_ci if there is no running event loop and no current loop is set. 1197db96d56Sopenharmony_ci In some future Python release this will become an error. 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci.. class:: WindowsSelectorEventLoopPolicy 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci An alternative event loop policy that uses the 1257db96d56Sopenharmony_ci :class:`SelectorEventLoop` event loop implementation. 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci .. availability:: Windows. 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci 1307db96d56Sopenharmony_ci.. class:: WindowsProactorEventLoopPolicy 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci An alternative event loop policy that uses the 1337db96d56Sopenharmony_ci :class:`ProactorEventLoop` event loop implementation. 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci .. availability:: Windows. 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci.. _asyncio-watchers: 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ciProcess Watchers 1417db96d56Sopenharmony_ci================ 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ciA process watcher allows customization of how an event loop monitors 1447db96d56Sopenharmony_cichild processes on Unix. Specifically, the event loop needs to know 1457db96d56Sopenharmony_ciwhen a child process has exited. 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ciIn asyncio, child processes are created with 1487db96d56Sopenharmony_ci:func:`create_subprocess_exec` and :meth:`loop.subprocess_exec` 1497db96d56Sopenharmony_cifunctions. 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ciasyncio defines the :class:`AbstractChildWatcher` abstract base class, which child 1527db96d56Sopenharmony_ciwatchers should implement, and has four different implementations: 1537db96d56Sopenharmony_ci:class:`ThreadedChildWatcher` (configured to be used by default), 1547db96d56Sopenharmony_ci:class:`MultiLoopChildWatcher`, :class:`SafeChildWatcher`, and 1557db96d56Sopenharmony_ci:class:`FastChildWatcher`. 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ciSee also the :ref:`Subprocess and Threads <asyncio-subprocess-threads>` 1587db96d56Sopenharmony_cisection. 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ciThe following two functions can be used to customize the child process watcher 1617db96d56Sopenharmony_ciimplementation used by the asyncio event loop: 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci.. function:: get_child_watcher() 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci Return the current child watcher for the current policy. 1667db96d56Sopenharmony_ci 1677db96d56Sopenharmony_ci.. function:: set_child_watcher(watcher) 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_ci Set the current child watcher to *watcher* for the current 1707db96d56Sopenharmony_ci policy. *watcher* must implement methods defined in the 1717db96d56Sopenharmony_ci :class:`AbstractChildWatcher` base class. 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci.. note:: 1747db96d56Sopenharmony_ci Third-party event loops implementations might not support 1757db96d56Sopenharmony_ci custom child watchers. For such event loops, using 1767db96d56Sopenharmony_ci :func:`set_child_watcher` might be prohibited or have no effect. 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci.. class:: AbstractChildWatcher 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci .. method:: add_child_handler(pid, callback, *args) 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci Register a new child handler. 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci Arrange for ``callback(pid, returncode, *args)`` to be called 1857db96d56Sopenharmony_ci when a process with PID equal to *pid* terminates. Specifying 1867db96d56Sopenharmony_ci another callback for the same process replaces the previous 1877db96d56Sopenharmony_ci handler. 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci The *callback* callable must be thread-safe. 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci .. method:: remove_child_handler(pid) 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci Removes the handler for process with PID equal to *pid*. 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci The function returns ``True`` if the handler was successfully 1967db96d56Sopenharmony_ci removed, ``False`` if there was nothing to remove. 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci .. method:: attach_loop(loop) 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci Attach the watcher to an event loop. 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci If the watcher was previously attached to an event loop, then 2037db96d56Sopenharmony_ci it is first detached before attaching to the new loop. 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci Note: loop may be ``None``. 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ci .. method:: is_active() 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci Return ``True`` if the watcher is ready to use. 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci Spawning a subprocess with *inactive* current child watcher raises 2127db96d56Sopenharmony_ci :exc:`RuntimeError`. 2137db96d56Sopenharmony_ci 2147db96d56Sopenharmony_ci .. versionadded:: 3.8 2157db96d56Sopenharmony_ci 2167db96d56Sopenharmony_ci .. method:: close() 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci Close the watcher. 2197db96d56Sopenharmony_ci 2207db96d56Sopenharmony_ci This method has to be called to ensure that underlying 2217db96d56Sopenharmony_ci resources are cleaned-up. 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ci.. class:: ThreadedChildWatcher 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci This implementation starts a new waiting thread for every subprocess spawn. 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci It works reliably even when the asyncio event loop is run in a non-main OS thread. 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci There is no noticeable overhead when handling a big number of children (*O(1)* each 2307db96d56Sopenharmony_ci time a child terminates), but starting a thread per process requires extra memory. 2317db96d56Sopenharmony_ci 2327db96d56Sopenharmony_ci This watcher is used by default. 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci .. versionadded:: 3.8 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ci.. class:: MultiLoopChildWatcher 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci This implementation registers a :py:data:`SIGCHLD` signal handler on 2397db96d56Sopenharmony_ci instantiation. That can break third-party code that installs a custom handler for 2407db96d56Sopenharmony_ci :py:data:`SIGCHLD` signal. 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ci The watcher avoids disrupting other code spawning processes 2437db96d56Sopenharmony_ci by polling every process explicitly on a :py:data:`SIGCHLD` signal. 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci There is no limitation for running subprocesses from different threads once the 2467db96d56Sopenharmony_ci watcher is installed. 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ci The solution is safe but it has a significant overhead when 2497db96d56Sopenharmony_ci handling a big number of processes (*O(n)* each time a 2507db96d56Sopenharmony_ci :py:data:`SIGCHLD` is received). 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci .. versionadded:: 3.8 2537db96d56Sopenharmony_ci 2547db96d56Sopenharmony_ci.. class:: SafeChildWatcher 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci This implementation uses active event loop from the main thread to handle 2577db96d56Sopenharmony_ci :py:data:`SIGCHLD` signal. If the main thread has no running event loop another 2587db96d56Sopenharmony_ci thread cannot spawn a subprocess (:exc:`RuntimeError` is raised). 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci The watcher avoids disrupting other code spawning processes 2617db96d56Sopenharmony_ci by polling every process explicitly on a :py:data:`SIGCHLD` signal. 2627db96d56Sopenharmony_ci 2637db96d56Sopenharmony_ci This solution is as safe as :class:`MultiLoopChildWatcher` and has the same *O(N)* 2647db96d56Sopenharmony_ci complexity but requires a running event loop in the main thread to work. 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ci.. class:: FastChildWatcher 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci This implementation reaps every terminated processes by calling 2697db96d56Sopenharmony_ci ``os.waitpid(-1)`` directly, possibly breaking other code spawning 2707db96d56Sopenharmony_ci processes and waiting for their termination. 2717db96d56Sopenharmony_ci 2727db96d56Sopenharmony_ci There is no noticeable overhead when handling a big number of 2737db96d56Sopenharmony_ci children (*O(1)* each time a child terminates). 2747db96d56Sopenharmony_ci 2757db96d56Sopenharmony_ci This solution requires a running event loop in the main thread to work, as 2767db96d56Sopenharmony_ci :class:`SafeChildWatcher`. 2777db96d56Sopenharmony_ci 2787db96d56Sopenharmony_ci.. class:: PidfdChildWatcher 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci This implementation polls process file descriptors (pidfds) to await child 2817db96d56Sopenharmony_ci process termination. In some respects, :class:`PidfdChildWatcher` is a 2827db96d56Sopenharmony_ci "Goldilocks" child watcher implementation. It doesn't require signals or 2837db96d56Sopenharmony_ci threads, doesn't interfere with any processes launched outside the event 2847db96d56Sopenharmony_ci loop, and scales linearly with the number of subprocesses launched by the 2857db96d56Sopenharmony_ci event loop. The main disadvantage is that pidfds are specific to Linux, and 2867db96d56Sopenharmony_ci only work on recent (5.3+) kernels. 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci .. versionadded:: 3.9 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci.. _asyncio-custom-policies: 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ciCustom Policies 2947db96d56Sopenharmony_ci=============== 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ciTo implement a new event loop policy, it is recommended to subclass 2977db96d56Sopenharmony_ci:class:`DefaultEventLoopPolicy` and override the methods for which 2987db96d56Sopenharmony_cicustom behavior is wanted, e.g.:: 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci class MyEventLoopPolicy(asyncio.DefaultEventLoopPolicy): 3017db96d56Sopenharmony_ci 3027db96d56Sopenharmony_ci def get_event_loop(self): 3037db96d56Sopenharmony_ci """Get the event loop. 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci This may be None or an instance of EventLoop. 3067db96d56Sopenharmony_ci """ 3077db96d56Sopenharmony_ci loop = super().get_event_loop() 3087db96d56Sopenharmony_ci # Do something with loop ... 3097db96d56Sopenharmony_ci return loop 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci asyncio.set_event_loop_policy(MyEventLoopPolicy()) 312