# Subprocesses — Python 3 documentation (asyncio.subprocess) ## Metadata | Field | Value | |---|---| | Institute | Molodetz Institute — Research & Retrieval Division | | Subject | async-pty-process-testing | | Document type | Source Dossier | | Tier | 1 | | Source title | Subprocesses — Python 3.14 documentation | | Source URL | https://docs.python.org/3/library/asyncio-subprocess.html | | Source publisher / author | Python Software Foundation | | Source type | standard (official stdlib documentation) | | Source date (published) | Unknown — not stated (continuously updated) | | Date researched | 2026-10-09 | | Researched by | tai (agent), model: Claude Sonnet 5, on behalf of retoor | | Research method | web search synthesis | | Confidence | High | | Status | Active | ## Summary The canonical stdlib reference for `asyncio.subprocess`, confirming the exact semantics of `terminate()`/`kill()`, how `Process.stdout`/`Process.stderr` expose `StreamReader` instances when `PIPE` is used, and the deadlock risk of reading those streams manually instead of via `communicate()`. ## Key findings - On POSIX, `Process.terminate()` sends SIGTERM to the child; `Process.kill()` sends SIGKILL. On Windows, `terminate()` calls the Win32 `TerminateProcess` API; there is no separate POSIX-signal distinction. - When `stdout=PIPE` or `stderr=PIPE` is passed, `Process.stdout`/`Process.stderr` are `asyncio.StreamReader` instances — the same abstraction `tai_test.py` wraps a pty master fd into via `loop.connect_read_pipe`, for a uniform interface across both transports. - The docs warn that reading those streams manually (rather than via `communicate()`) can deadlock, because the child can block on a full pipe buffer if its output isn't drained quickly enough while it's also waiting on something else. ## Pros / strengths - Authoritative, primary-source documentation — the single most load-bearing source in this entire subject for API semantics. ## Cons / limitations / caveats - Documents stdlib behavior as of whatever version was fetched; does not itself discuss process-group-wide termination (`killpg`) or the controlling-terminal/pty nuances this subject's other sources cover — those required separate sources. ## Relevance to tai The definitive basis for `tai_test.py`'s choice of `terminate()` (SIGTERM) before escalating to `kill()` (SIGKILL) in `ManagedProcess.terminate()`'s escalation loop, and for exposing `Process.stdout`/`Process.stderr` as the pipe-mode reader rather than hand-rolling a reader over raw fds in that transport. The deadlock warning is why `ManagedProcess.drain_until_eof()` continuously reads in a loop until EOF rather than attempting a single large read. ## Changelog | Date | Change | |---|---| | 2026-10-09 | Initial dossier created. |