17db96d56Sopenharmony_ci.. currentmodule:: asyncio
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci.. _asyncio-subprocess:
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ci============
67db96d56Sopenharmony_ciSubprocesses
77db96d56Sopenharmony_ci============
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci**Source code:** :source:`Lib/asyncio/subprocess.py`,
107db96d56Sopenharmony_ci:source:`Lib/asyncio/base_subprocess.py`
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci----------------------------------------
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ciThis section describes high-level async/await asyncio APIs to
157db96d56Sopenharmony_cicreate and manage subprocesses.
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci.. _asyncio_example_subprocess_shell:
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ciHere's an example of how asyncio can run a shell command and
207db96d56Sopenharmony_ciobtain its result::
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci    import asyncio
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_ci    async def run(cmd):
257db96d56Sopenharmony_ci        proc = await asyncio.create_subprocess_shell(
267db96d56Sopenharmony_ci            cmd,
277db96d56Sopenharmony_ci            stdout=asyncio.subprocess.PIPE,
287db96d56Sopenharmony_ci            stderr=asyncio.subprocess.PIPE)
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci        stdout, stderr = await proc.communicate()
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ci        print(f'[{cmd!r} exited with {proc.returncode}]')
337db96d56Sopenharmony_ci        if stdout:
347db96d56Sopenharmony_ci            print(f'[stdout]\n{stdout.decode()}')
357db96d56Sopenharmony_ci        if stderr:
367db96d56Sopenharmony_ci            print(f'[stderr]\n{stderr.decode()}')
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_ci    asyncio.run(run('ls /zzz'))
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ciwill print::
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci    ['ls /zzz' exited with 1]
437db96d56Sopenharmony_ci    [stderr]
447db96d56Sopenharmony_ci    ls: /zzz: No such file or directory
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ciBecause all asyncio subprocess functions are asynchronous and asyncio
477db96d56Sopenharmony_ciprovides many tools to work with such functions, it is easy to execute
487db96d56Sopenharmony_ciand monitor multiple subprocesses in parallel.  It is indeed trivial
497db96d56Sopenharmony_cito modify the above example to run several commands simultaneously::
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci    async def main():
527db96d56Sopenharmony_ci        await asyncio.gather(
537db96d56Sopenharmony_ci            run('ls /zzz'),
547db96d56Sopenharmony_ci            run('sleep 1; echo "hello"'))
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci    asyncio.run(main())
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ciSee also the `Examples`_ subsection.
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ciCreating Subprocesses
627db96d56Sopenharmony_ci=====================
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci.. coroutinefunction:: create_subprocess_exec(program, *args, stdin=None, \
657db96d56Sopenharmony_ci                          stdout=None, stderr=None, limit=None, **kwds)
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci   Create a subprocess.
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci   The *limit* argument sets the buffer limit for :class:`StreamReader`
707db96d56Sopenharmony_ci   wrappers for :attr:`Process.stdout` and :attr:`Process.stderr`
717db96d56Sopenharmony_ci   (if :attr:`subprocess.PIPE` is passed to *stdout* and *stderr* arguments).
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci   Return a :class:`~asyncio.subprocess.Process` instance.
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci   See the documentation of :meth:`loop.subprocess_exec` for other
767db96d56Sopenharmony_ci   parameters.
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci   .. versionchanged:: 3.10
797db96d56Sopenharmony_ci      Removed the *loop* parameter.
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci.. coroutinefunction:: create_subprocess_shell(cmd, stdin=None, \
837db96d56Sopenharmony_ci                          stdout=None, stderr=None, limit=None, **kwds)
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ci   Run the *cmd* shell command.
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci   The *limit* argument sets the buffer limit for :class:`StreamReader`
887db96d56Sopenharmony_ci   wrappers for :attr:`Process.stdout` and :attr:`Process.stderr`
897db96d56Sopenharmony_ci   (if :attr:`subprocess.PIPE` is passed to *stdout* and *stderr* arguments).
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ci   Return a :class:`~asyncio.subprocess.Process` instance.
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci   See the documentation of :meth:`loop.subprocess_shell` for other
947db96d56Sopenharmony_ci   parameters.
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci   .. important::
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ci      It is the application's responsibility to ensure that all whitespace and
997db96d56Sopenharmony_ci      special characters are quoted appropriately to avoid `shell injection
1007db96d56Sopenharmony_ci      <https://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
1017db96d56Sopenharmony_ci      vulnerabilities. The :func:`shlex.quote` function can be used to properly
1027db96d56Sopenharmony_ci      escape whitespace and special shell characters in strings that are going
1037db96d56Sopenharmony_ci      to be used to construct shell commands.
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci   .. versionchanged:: 3.10
1067db96d56Sopenharmony_ci      Removed the *loop* parameter.
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ci.. note::
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci   Subprocesses are available for Windows if a :class:`ProactorEventLoop` is
1117db96d56Sopenharmony_ci   used. See :ref:`Subprocess Support on Windows <asyncio-windows-subprocess>`
1127db96d56Sopenharmony_ci   for details.
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci.. seealso::
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ci   asyncio also has the following *low-level* APIs to work with subprocesses:
1177db96d56Sopenharmony_ci   :meth:`loop.subprocess_exec`, :meth:`loop.subprocess_shell`,
1187db96d56Sopenharmony_ci   :meth:`loop.connect_read_pipe`, :meth:`loop.connect_write_pipe`,
1197db96d56Sopenharmony_ci   as well as the :ref:`Subprocess Transports <asyncio-subprocess-transports>`
1207db96d56Sopenharmony_ci   and :ref:`Subprocess Protocols <asyncio-subprocess-protocols>`.
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ciConstants
1247db96d56Sopenharmony_ci=========
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci.. data:: asyncio.subprocess.PIPE
1277db96d56Sopenharmony_ci   :module:
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci   Can be passed to the *stdin*, *stdout* or *stderr* parameters.
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci   If *PIPE* is passed to *stdin* argument, the
1327db96d56Sopenharmony_ci   :attr:`Process.stdin <asyncio.subprocess.Process.stdin>` attribute
1337db96d56Sopenharmony_ci   will point to a :class:`StreamWriter` instance.
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci   If *PIPE* is passed to *stdout* or *stderr* arguments, the
1367db96d56Sopenharmony_ci   :attr:`Process.stdout <asyncio.subprocess.Process.stdout>` and
1377db96d56Sopenharmony_ci   :attr:`Process.stderr <asyncio.subprocess.Process.stderr>`
1387db96d56Sopenharmony_ci   attributes will point to :class:`StreamReader` instances.
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci.. data:: asyncio.subprocess.STDOUT
1417db96d56Sopenharmony_ci   :module:
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci   Special value that can be used as the *stderr* argument and indicates
1447db96d56Sopenharmony_ci   that standard error should be redirected into standard output.
1457db96d56Sopenharmony_ci
1467db96d56Sopenharmony_ci.. data:: asyncio.subprocess.DEVNULL
1477db96d56Sopenharmony_ci   :module:
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci   Special value that can be used as the *stdin*, *stdout* or *stderr* argument
1507db96d56Sopenharmony_ci   to process creation functions.  It indicates that the special file
1517db96d56Sopenharmony_ci   :data:`os.devnull` will be used for the corresponding subprocess stream.
1527db96d56Sopenharmony_ci
1537db96d56Sopenharmony_ci
1547db96d56Sopenharmony_ciInteracting with Subprocesses
1557db96d56Sopenharmony_ci=============================
1567db96d56Sopenharmony_ci
1577db96d56Sopenharmony_ciBoth :func:`create_subprocess_exec` and :func:`create_subprocess_shell`
1587db96d56Sopenharmony_cifunctions return instances of the *Process* class.  *Process* is a high-level
1597db96d56Sopenharmony_ciwrapper that allows communicating with subprocesses and watching for
1607db96d56Sopenharmony_citheir completion.
1617db96d56Sopenharmony_ci
1627db96d56Sopenharmony_ci.. class:: asyncio.subprocess.Process
1637db96d56Sopenharmony_ci   :module:
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci   An object that wraps OS processes created by the
1667db96d56Sopenharmony_ci   :func:`create_subprocess_exec` and :func:`create_subprocess_shell`
1677db96d56Sopenharmony_ci   functions.
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci   This class is designed to have a similar API to the
1707db96d56Sopenharmony_ci   :class:`subprocess.Popen` class, but there are some
1717db96d56Sopenharmony_ci   notable differences:
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci   * unlike Popen, Process instances do not have an equivalent to
1747db96d56Sopenharmony_ci     the :meth:`~subprocess.Popen.poll` method;
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ci   * the :meth:`~asyncio.subprocess.Process.communicate` and
1777db96d56Sopenharmony_ci     :meth:`~asyncio.subprocess.Process.wait` methods don't have a
1787db96d56Sopenharmony_ci     *timeout* parameter: use the :func:`~asyncio.wait_for` function;
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ci   * the :meth:`Process.wait() <asyncio.subprocess.Process.wait>` method
1817db96d56Sopenharmony_ci     is asynchronous, whereas :meth:`subprocess.Popen.wait` method
1827db96d56Sopenharmony_ci     is implemented as a blocking busy loop;
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci   * the *universal_newlines* parameter is not supported.
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci   This class is :ref:`not thread safe <asyncio-multithreading>`.
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ci   See also the :ref:`Subprocess and Threads <asyncio-subprocess-threads>`
1897db96d56Sopenharmony_ci   section.
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci   .. coroutinemethod:: wait()
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci      Wait for the child process to terminate.
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci      Set and return the :attr:`returncode` attribute.
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ci      .. note::
1987db96d56Sopenharmony_ci
1997db96d56Sopenharmony_ci         This method can deadlock when using ``stdout=PIPE`` or
2007db96d56Sopenharmony_ci         ``stderr=PIPE`` and the child process generates so much output
2017db96d56Sopenharmony_ci         that it blocks waiting for the OS pipe buffer to accept
2027db96d56Sopenharmony_ci         more data. Use the :meth:`communicate` method when using pipes
2037db96d56Sopenharmony_ci         to avoid this condition.
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci   .. coroutinemethod:: communicate(input=None)
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_ci      Interact with process:
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ci      1. send data to *stdin* (if *input* is not ``None``);
2107db96d56Sopenharmony_ci      2. read data from *stdout* and *stderr*, until EOF is reached;
2117db96d56Sopenharmony_ci      3. wait for process to terminate.
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_ci      The optional *input* argument is the data (:class:`bytes` object)
2147db96d56Sopenharmony_ci      that will be sent to the child process.
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci      Return a tuple ``(stdout_data, stderr_data)``.
2177db96d56Sopenharmony_ci
2187db96d56Sopenharmony_ci      If either :exc:`BrokenPipeError` or :exc:`ConnectionResetError`
2197db96d56Sopenharmony_ci      exception is raised when writing *input* into *stdin*, the
2207db96d56Sopenharmony_ci      exception is ignored.  This condition occurs when the process
2217db96d56Sopenharmony_ci      exits before all data are written into *stdin*.
2227db96d56Sopenharmony_ci
2237db96d56Sopenharmony_ci      If it is desired to send data to the process' *stdin*,
2247db96d56Sopenharmony_ci      the process needs to be created with ``stdin=PIPE``.  Similarly,
2257db96d56Sopenharmony_ci      to get anything other than ``None`` in the result tuple, the
2267db96d56Sopenharmony_ci      process has to be created with ``stdout=PIPE`` and/or
2277db96d56Sopenharmony_ci      ``stderr=PIPE`` arguments.
2287db96d56Sopenharmony_ci
2297db96d56Sopenharmony_ci      Note, that the data read is buffered in memory, so do not use
2307db96d56Sopenharmony_ci      this method if the data size is large or unlimited.
2317db96d56Sopenharmony_ci
2327db96d56Sopenharmony_ci   .. method:: send_signal(signal)
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_ci      Sends the signal *signal* to the child process.
2357db96d56Sopenharmony_ci
2367db96d56Sopenharmony_ci      .. note::
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci         On Windows, :py:data:`SIGTERM` is an alias for :meth:`terminate`.
2397db96d56Sopenharmony_ci         ``CTRL_C_EVENT`` and ``CTRL_BREAK_EVENT`` can be sent to processes
2407db96d56Sopenharmony_ci         started with a *creationflags* parameter which includes
2417db96d56Sopenharmony_ci         ``CREATE_NEW_PROCESS_GROUP``.
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ci   .. method:: terminate()
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci      Stop the child process.
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci      On POSIX systems this method sends :py:data:`signal.SIGTERM` to the
2487db96d56Sopenharmony_ci      child process.
2497db96d56Sopenharmony_ci
2507db96d56Sopenharmony_ci      On Windows the Win32 API function :c:func:`TerminateProcess` is
2517db96d56Sopenharmony_ci      called to stop the child process.
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci   .. method:: kill()
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci      Kill the child process.
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci      On POSIX systems this method sends :py:data:`SIGKILL` to the child
2587db96d56Sopenharmony_ci      process.
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ci      On Windows this method is an alias for :meth:`terminate`.
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci   .. attribute:: stdin
2637db96d56Sopenharmony_ci
2647db96d56Sopenharmony_ci      Standard input stream (:class:`StreamWriter`) or ``None``
2657db96d56Sopenharmony_ci      if the process was created with ``stdin=None``.
2667db96d56Sopenharmony_ci
2677db96d56Sopenharmony_ci   .. attribute:: stdout
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci      Standard output stream (:class:`StreamReader`) or ``None``
2707db96d56Sopenharmony_ci      if the process was created with ``stdout=None``.
2717db96d56Sopenharmony_ci
2727db96d56Sopenharmony_ci   .. attribute:: stderr
2737db96d56Sopenharmony_ci
2747db96d56Sopenharmony_ci      Standard error stream (:class:`StreamReader`) or ``None``
2757db96d56Sopenharmony_ci      if the process was created with ``stderr=None``.
2767db96d56Sopenharmony_ci
2777db96d56Sopenharmony_ci   .. warning::
2787db96d56Sopenharmony_ci
2797db96d56Sopenharmony_ci      Use the :meth:`communicate` method rather than
2807db96d56Sopenharmony_ci      :attr:`process.stdin.write() <stdin>`,
2817db96d56Sopenharmony_ci      :attr:`await process.stdout.read() <stdout>` or
2827db96d56Sopenharmony_ci      :attr:`await process.stderr.read() <stderr>`.
2837db96d56Sopenharmony_ci      This avoids deadlocks due to streams pausing reading or writing
2847db96d56Sopenharmony_ci      and blocking the child process.
2857db96d56Sopenharmony_ci
2867db96d56Sopenharmony_ci   .. attribute:: pid
2877db96d56Sopenharmony_ci
2887db96d56Sopenharmony_ci      Process identification number (PID).
2897db96d56Sopenharmony_ci
2907db96d56Sopenharmony_ci      Note that for processes created by the :func:`create_subprocess_shell`
2917db96d56Sopenharmony_ci      function, this attribute is the PID of the spawned shell.
2927db96d56Sopenharmony_ci
2937db96d56Sopenharmony_ci   .. attribute:: returncode
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ci      Return code of the process when it exits.
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ci      A ``None`` value indicates that the process has not terminated yet.
2987db96d56Sopenharmony_ci
2997db96d56Sopenharmony_ci      A negative value ``-N`` indicates that the child was terminated
3007db96d56Sopenharmony_ci      by signal ``N`` (POSIX only).
3017db96d56Sopenharmony_ci
3027db96d56Sopenharmony_ci
3037db96d56Sopenharmony_ci.. _asyncio-subprocess-threads:
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ciSubprocess and Threads
3067db96d56Sopenharmony_ci----------------------
3077db96d56Sopenharmony_ci
3087db96d56Sopenharmony_ciStandard asyncio event loop supports running subprocesses from different threads by
3097db96d56Sopenharmony_cidefault.
3107db96d56Sopenharmony_ci
3117db96d56Sopenharmony_ciOn Windows subprocesses are provided by :class:`ProactorEventLoop` only (default),
3127db96d56Sopenharmony_ci:class:`SelectorEventLoop` has no subprocess support.
3137db96d56Sopenharmony_ci
3147db96d56Sopenharmony_ciOn UNIX *child watchers* are used for subprocess finish waiting, see
3157db96d56Sopenharmony_ci:ref:`asyncio-watchers` for more info.
3167db96d56Sopenharmony_ci
3177db96d56Sopenharmony_ci
3187db96d56Sopenharmony_ci.. versionchanged:: 3.8
3197db96d56Sopenharmony_ci
3207db96d56Sopenharmony_ci   UNIX switched to use :class:`ThreadedChildWatcher` for spawning subprocesses from
3217db96d56Sopenharmony_ci   different threads without any limitation.
3227db96d56Sopenharmony_ci
3237db96d56Sopenharmony_ci   Spawning a subprocess with *inactive* current child watcher raises
3247db96d56Sopenharmony_ci   :exc:`RuntimeError`.
3257db96d56Sopenharmony_ci
3267db96d56Sopenharmony_ciNote that alternative event loop implementations might have own limitations;
3277db96d56Sopenharmony_ciplease refer to their documentation.
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci.. seealso::
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ci   The :ref:`Concurrency and multithreading in asyncio
3327db96d56Sopenharmony_ci   <asyncio-multithreading>` section.
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_ci
3357db96d56Sopenharmony_ciExamples
3367db96d56Sopenharmony_ci--------
3377db96d56Sopenharmony_ci
3387db96d56Sopenharmony_ciAn example using the :class:`~asyncio.subprocess.Process` class to
3397db96d56Sopenharmony_cicontrol a subprocess and the :class:`StreamReader` class to read from
3407db96d56Sopenharmony_ciits standard output.
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_ci.. _asyncio_example_create_subprocess_exec:
3437db96d56Sopenharmony_ci
3447db96d56Sopenharmony_ciThe subprocess is created by the :func:`create_subprocess_exec`
3457db96d56Sopenharmony_cifunction::
3467db96d56Sopenharmony_ci
3477db96d56Sopenharmony_ci    import asyncio
3487db96d56Sopenharmony_ci    import sys
3497db96d56Sopenharmony_ci
3507db96d56Sopenharmony_ci    async def get_date():
3517db96d56Sopenharmony_ci        code = 'import datetime; print(datetime.datetime.now())'
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci        # Create the subprocess; redirect the standard output
3547db96d56Sopenharmony_ci        # into a pipe.
3557db96d56Sopenharmony_ci        proc = await asyncio.create_subprocess_exec(
3567db96d56Sopenharmony_ci            sys.executable, '-c', code,
3577db96d56Sopenharmony_ci            stdout=asyncio.subprocess.PIPE)
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci        # Read one line of output.
3607db96d56Sopenharmony_ci        data = await proc.stdout.readline()
3617db96d56Sopenharmony_ci        line = data.decode('ascii').rstrip()
3627db96d56Sopenharmony_ci
3637db96d56Sopenharmony_ci        # Wait for the subprocess exit.
3647db96d56Sopenharmony_ci        await proc.wait()
3657db96d56Sopenharmony_ci        return line
3667db96d56Sopenharmony_ci
3677db96d56Sopenharmony_ci    date = asyncio.run(get_date())
3687db96d56Sopenharmony_ci    print(f"Current date: {date}")
3697db96d56Sopenharmony_ci
3707db96d56Sopenharmony_ci
3717db96d56Sopenharmony_ciSee also the :ref:`same example <asyncio_example_subprocess_proto>`
3727db96d56Sopenharmony_ciwritten using low-level APIs.
373