subprocess.communicate ()에서 스트리밍 입력 읽기
subprocess.communicate()
약 1 분 동안 실행되는 프로세스에서 표준 출력을 읽기 위해 Python을 사용 하고 있습니다.
해당 프로세스의 각 줄을 stdout
스트리밍 방식으로 인쇄하여 생성 된 출력을 볼 수 있지만 계속하기 전에 프로세스가 종료되는 것을 차단하려면 어떻게해야합니까?
subprocess.communicate()
한 번에 모든 출력을 제공하는 것처럼 보입니다.
내가 생각하는주의 사항 (아래) JF 세바스찬의 방법은 더 좋다.
다음은 오류를 확인하지 않는 간단한 예입니다.
import subprocess
proc = subprocess.Popen('ls',
shell=True,
stdout=subprocess.PIPE,
)
while proc.poll() is None:
output = proc.stdout.readline()
print output,
경우 ls
모든 데이터를 읽은 전에 끝이 너무 빨리, 그 동안 루프가 종료 될 수 있습니다.
다음과 같이 stdout에서 나머지를 잡을 수 있습니다.
output = proc.communicate()[0]
print output,
하위 프로세스가 stdout 버퍼를 플러시하자마자 하위 프로세스의 출력을 한 줄씩 가져 오려면 :
#!/usr/bin/env python2
from subprocess import Popen, PIPE
p = Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1)
with p.stdout:
for line in iter(p.stdout.readline, b''):
print line,
p.wait() # wait for the subprocess to exit
iter()
Python 2의 미리 읽기 버그 를 해결 하기 위해 작성되는 즉시 행을 읽는 데 사용됩니다 .
하위 프로세스의 stdout이 비대화 형 모드에서 라인 버퍼링 대신 블록 버퍼링을 사용하는 경우 (이로 인해 자식의 버퍼가 가득 차거나 자식이 명시 적으로 플러시 할 때까지 출력이 지연됨) 다음을 사용하여 버퍼링되지 않은 출력을 강제로 시도 할 수 있습니다. pexpect
, pty
모듈 또는 unbuffer
, stdbuf
, script
유틸리티 , 참조 왜 그냥 파이프 사용 (는 popen을 ()) : Q는?
다음은 Python 3 코드입니다.
#!/usr/bin/env python3
from subprocess import Popen, PIPE
with Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1,
universal_newlines=True) as p:
for line in p.stdout:
print(line, end='')
참고 : 하위 프로세스의 바이트 문자열을있는 그대로 출력하는 Python 2와 달리; Python 3은 텍스트 모드를 사용합니다 (cmd의 출력은 locale.getpreferredencoding(False)
인코딩을 사용하여 디코딩 됨 ).
스트리밍 방식으로 프로세스에서 출력을 수집하는 가장 간단한 방법은 다음과 같습니다.
import sys
from subprocess import *
proc = Popen('ls', shell=True, stdout=PIPE)
while True:
data = proc.stdout.readline() # Alternatively proc.stdout.read(1024)
if len(data) == 0:
break
sys.stdout.write(data) # sys.stdout.buffer.write(data) on Python 3.x
readline()
또는 read()
읽을 수있는 것도이 (가없는 경우 그렇지 않은 경우는 차단 - 기능은 프로세스가 종료 된 후, EOF에 빈 문자열을 반환해야합니다 readline()
, 줄 바꿈을 포함하므로 빈 줄에, 그것은 반환 "\ n"). 이렇게하면 communicate()
루프 후 어색한 최종 호출 이 필요하지 않습니다 .
줄 read()
이 매우 긴 파일에서는 최대 메모리 사용량을 줄이는 것이 바람직 할 수 있습니다. 전달 된 수는 임의적이지만이를 제외하면 전체 파이프 출력을 한 번에 읽는 것이 바람직하지 않을 수 있습니다.
비 차단 접근 방식을 원하면 process.communicate()
. subprocess.Popen()
인수 stdout
를로 설정하면 PIPE
에서 읽고 process.stdout
프로세스가 여전히을 사용하여 실행되는지 확인할 수 있습니다 process.poll()
.
If you're simply trying to pass the output through in realtime, it's hard to get simpler than this:
import subprocess
# This will raise a CalledProcessError if the program return a nonzero code.
# You can use call() instead if you don't care about that case.
subprocess.check_call(['ls', '-l'])
See the docs for subprocess.check_call().
If you need to process the output, sure, loop on it. But if you don't, just keep it simple.
Edit: J.F. Sebastian points out both that the defaults for the stdout and stderr parameters pass through to sys.stdout and sys.stderr, and that this will fail if sys.stdout and sys.stderr have been replaced (say, for capturing output in tests).
myCommand="ls -l"
cmd=myCommand.split()
# "universal newline support" This will cause to interpret \n, \r\n and \r equally, each as a newline.
p = subprocess.Popen(cmd, stderr=subprocess.PIPE, universal_newlines=True)
while True:
print(p.stderr.readline().rstrip('\r\n'))
참고URL : https://stackoverflow.com/questions/2715847/read-streaming-input-from-subprocess-communicate
'program tip' 카테고리의 다른 글
Laravel과 Eloquent를 사용하여 두 날짜 사이를 쿼리하는 방법은 무엇입니까? (0) | 2020.10.23 |
---|---|
자바 스크립트의 해시에서 키 + 값을 제거하는 방법 (0) | 2020.10.23 |
건초 더미에서 바늘을 어떻게 찾습니까? (0) | 2020.10.23 |
자바 : 명령 줄에서 jar 파일을 가져 오는 방법 (0) | 2020.10.23 |
프로덕션 JavaScript 코드에 "console.log ()"호출을 남겨 두는 것이 좋지 않습니까? (0) | 2020.10.23 |