PEP 3145 – subprocess.Popen을 위한 비동기 I/O
- Author:
- Eric Pruitt, Charles R. McCreary, Josiah Carlson
- Status:
- Withdrawn
- Type:
- Standards Track
- Created:
- 04-Aug-2009
- Python-Version:
- 3.2
- Post-History:
번역·라이선스 안내
이 문서는 Open Publication License v1.0 이상에 따라 만든 수정된 한국어 번역본입니다. 수정자: yeokja/yeokja 프로젝트. 수정일: 2026-08-29. 변경 내용: 영어 원문을 한국어로 번역했습니다. 원저자와 저작권 표시는 위 Author 필드와 아래 Copyright 절에 유지했으며, 이 번역은 원저자의 승인이나 보증을 뜻하지 않습니다. 수정되지 않은 기준 원문 · 공식 최신판 · Open Publication License v1.0
초록
현재 형태의 subprocess.Popen 구현은 자식 프로세스의 데이터를 기다리는 동안 부모 Python 스크립트가 교착 상태에 빠지거나 차단되기 쉽습니다. 이 PEP에서는 이러한 문제를 완화하기 위해 subprocess.Popen을 더욱 비동기적으로 만들 것을 제안합니다.
PEP 연기
이 PEP에서 다루는 개념에 대한 추가 탐구는 PEP 3156이 해결된 이후까지 최소한 연기되었습니다.
PEP 철회
이는 버그 추적기에서 처리할 수 있습니다. 구체적인 제안이 [11]에 첨부되어 있습니다.
동기
“python asynchronous subprocess”를 검색하면 자식 프로세스를 실행하고, 프로그램이 데이터를 생성할 때까지 차단하여 기다리는 대신 사용 가능한 데이터만 때때로 읽으면서 자식 프로세스와 통신하려는 사람들의 수많은 사례를 확인할 수 있습니다 [1] [2] [3]. 현재 subprocess 모듈의 동작에서는 사용자가 stdin, stderr 및 stdout 파일 객체를 통해 데이터를 보내거나 받을 때 교착 상태가 흔히 발생하며 문서화되어 있습니다 [4] [5]. 버퍼링 문제의 일부를 완화하기 위해 communicate를 사용할 수 있지만, 자식 프로세스에서 읽을 데이터가 없을 때 데이터를 읽으려고 시도하는 동안에도 부모 프로세스를 차단합니다.
근거
subprocess.Popen에는 비동기식 비차단 기능이 필요하다는 점이 문서화되어 있습니다 [6] [7] [2] [3]. 이 코드를 포함하면 Unix 기반 및 Windows 빌드의 Python에서 사용할 수 있는 Python 표준 라이브러리의 유용성이 향상됩니다. Python의 거의 모든 I/O 객체에는 어떤 형태로든 파일과 유사한 래퍼가 있습니다. 소켓은 이미 이러한 방식으로 동작하며 문자열에는 StringIO가 있습니다. subprocess.Popen.stderr, stdout 및 stdin 파일과 유사한 객체에 연결된 메서드를 간단히 사용하면 Popen이 파일처럼 동작하도록 만들 수 있습니다. 그러나 이러한 옵션의 읽기 및 쓰기 메서드를 사용할 때는 비동기 I/O의 이점을 얻을 수 없습니다. 제안된 해결책에서는 래퍼가 비동기 메서드를 감싸 파일 객체를 모방합니다.
참조 구현
테스트와 문서를 비롯한 모든 변경 사항이 포함된 Google Code 저장소 [9]와 개발 과정에서 겪은 문제를 자세히 설명하는 블로그 [10]를 유지 관리해 왔습니다.
subprocess 모듈에 비차단 비동기 I/O를 구현하는 동시에, 실행된 프로세스가 파일 객체의 모든 메서드와 속성을 복제하여 파일을 대신할 수 있도록 하는 subprocess.Popen용 래퍼 클래스를 구현하고 있습니다.
subprocess.Popen 클래스에는 두 개의 기본 함수인 Popen.send와 Popen._recv가 추가되었으며, 각각 Windows용과 Unix 기반 시스템용으로 별도의 구현이 제공됩니다. Windows 구현은 ctypes를 사용하여 kernel 32 DLL에서 파이프를 비동기 방식으로 제어하는 데 필요한 함수에 접근합니다. Unix 기반 시스템에서는 파일 제어를 위한 Python 인터페이스가 같은 목적을 수행합니다. Popen.send와 Popen._recv의 서로 다른 구현은 인수가 동일하므로 이러한 함수를 사용하는 코드가 여러 플랫폼에서 작동합니다.
Popen._recv 함수를 호출할 때는 파이프 이름을 인자로 전달해야 하므로, Popen._recv에서 기본적으로 stdout을 파이프로 선택하도록 하는 Popen.recv 함수가 존재합니다. Popen.recv_err는 기본적으로 stderr를 파이프로 선택합니다. Popen.recv와 Popen.recv_err는 각각 Popen._recv('stdout' ...) 및 Popen._recv('stderr' ...)보다 읽고 이해하기가 훨씬 쉽습니다.
Popen._recv 함수는 값을 반환하기 전에 데이터가 생성될 때까지 기다리지 않으므로 빈 바이트를 반환할 수 있습니다. Popen.asyncread는 지정된 시간 간격 동안 읽은 모든 데이터를 반환하여 이 문제를 처리합니다.
ProcessIOWrapper 클래스는 asyncread 및 asyncwrite 함수를 사용하여 프로세스가 파일처럼 동작하도록 하므로, subprocess.Popen 호출에서 생성된 stdout 및 stdin 파일 객체를 사용할 때 발생할 수 있는 차단 문제가 없습니다.
참고 자료
[8] subprocess.rst - subprocdev - Google Code 프로젝트 호스팅 https://web.archive.org/web/20130306074135/http://code.google.com/p/subprocdev/source/browse/doc/subprocess.rst?spec=svn2c925e935cad0166d5da85e37c742d8e7f609de5&r=2c925e935cad0166d5da85e37c742d8e7f609de5
Copyright
This P.E.P. is licensed under the Open Publication License; http://www.opencontent.org/openpub/.