여기에 대한 답변 중 어느 것도 나의 모든 요구를 해결하지 못했습니다.
- stdout에 대한 스레드가 없습니다 (큐 등도 없음)
- 다른 일이 있는지 확인해야 할 때 비 차단
- 스트림 출력, 로그 파일에 쓰기 및 출력의 문자열 복사본을 반환하는 등 여러 작업을 수행하는 데 필요한 PIPE를 사용하십시오.
약간의 배경 : ThreadPoolExecutor를 사용하여 스레드 풀을 관리하고 있습니다. 각 스레드는 하위 프로세스를 시작하고 동시성을 실행합니다. (Python2.7에서는 최신 3.x에서도 작동합니다). 나는 다른 것들을 위해 가능한 많은 것을 원하기 때문에 출력 수집을 위해 스레드를 사용하고 싶지 않습니다 (20 개의 프로세스 풀은 40 개의 스레드를 사용하여 실행됩니다 .1은 프로세스 스레드와 1은 stdout입니다 ... stderr를 원한다면 더 많이 추측합니다)
나는 많은 예외를 제거하고 있으며 여기서는 프로덕션에서 작동하는 코드를 기반 으로합니다. 잘만되면 나는 그것을 복사하여 붙여 넣기를 망치지 않았습니다. 또한 피드백은 대단히 환영합니다!
import time
import fcntl
import subprocess
import time
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# Make stdout non-blocking when using read/readline
proc_stdout = proc.stdout
fl = fcntl.fcntl(proc_stdout, fcntl.F_GETFL)
fcntl.fcntl(proc_stdout, fcntl.F_SETFL, fl | os.O_NONBLOCK)
def handle_stdout(proc_stream, my_buffer, echo_streams=True, log_file=None):
"""A little inline function to handle the stdout business. """
# fcntl makes readline non-blocking so it raises an IOError when empty
try:
for s in iter(proc_stream.readline, ''): # replace '' with b'' for Python 3
my_buffer.append(s)
if echo_streams:
sys.stdout.write(s)
if log_file:
log_file.write(s)
except IOError:
pass
# The main loop while subprocess is running
stdout_parts = []
while proc.poll() is None:
handle_stdout(proc_stdout, stdout_parts)
# ...Check for other things here...
# For example, check a multiprocessor.Value('b') to proc.kill()
time.sleep(0.01)
# Not sure if this is needed, but run it again just to be sure we got it all?
handle_stdout(proc_stdout, stdout_parts)
stdout_str = "".join(stdout_parts) # Just to demo
여기에 오버 헤드가 추가 될 것이라고 확신하지만 내 경우에는 문제가되지 않습니다. 기능적으로 그것은 내가 필요한 일을합니다. 내가 해결하지 않은 유일한 것은 이것이 로그 메시지에 완벽하게 작동하는 이유이지만 print
나중에 일부 메시지가 한 번에 표시되는 것을 볼 수 있습니다 .