Imported from sxarsky/eval-prefect (
src/prefect/utilities/processutils/AGENTS.md). Install upstream withnpx skills add sxarsky/eval-prefect --skill processutils. Copyright stays with the author.
processutils
Subprocess execution, output streaming, command serialization, and signal forwarding.
Purpose & Scope
Cross-platform subprocess primitives used by workers, runners, bundle execution, and the CLI. Handles process launch (run_process), output consumption (consume_process_output, stream_text), and platform-neutral command serialization (command_to_string, command_from_string).
Entry Points
sanitize_subprocess_env(env) -> dict[str, str]— stripNonevalues from an env mapping before passing to subprocess launch APIs;Nonemeans "omit this key", whichsubprocessandanyio.open_processdo not accept.run_process(command, ...)— async subprocess runner with output streaming and signal forwarding.consume_process_output(process, stdout_sink, stderr_sink)— drain a running process's streams into writers.stream_text(source, *sinks)— fan out a text stream to multiple sinks.command_to_string(command: list[str]) -> str/command_from_string(s: str) -> list[str]— platform-neutral serialize/deserialize of command arrays for storage and cross-platform bundles.get_sys_executable() -> str—sys.executablewith platform-appropriate handling (see pitfalls).
Pitfalls
- Non-UTF-8 subprocess output is silently replaced.
consume_process_outputandstream_text(viaTextReceiveStream(errors="replace")) replace invalid bytes with the Unicode replacement character\ufffdrather than raising. If captured output contains\ufffd, the subprocess emitted bytes that were not valid UTF-8. command_to_stringalways uses POSIX quoting (shlex.join), even on Windows. This is intentional for platform-neutral storage — bundle commands are serialized by one platform and may be deserialized by another.command_from_stringuses a dual-path approach: if the string was POSIX-serialized by Prefect (round-trips cleanly throughshlex.split/shlex.join), it uses POSIX parsing; otherwise it falls back to native Windows command-line parsing (CommandLineToArgvW). Do not use" ".join(command)orshlex.split(command)directly when working with stored Prefect commands — use these helpers instead.get_sys_executable()no longer quotes the Python path on Windows. It previously returned'"path/to/python"'(with embedded quotes) on Windows; now it returns the raw path. Code relying on the old quoted form (e.g., joining into a shell string) will break — usesubprocess.list2cmdlineorcommand_to_stringfor shell-safe serialization instead.