Python 하위 프로세스 실행 중 Stdout 읽기
-
Python 하위 프로세스 실행 중
stdout
읽기 -
접근법 1: Python에서 실행하는 동안
check_call
을 사용하여subprocess
의stdout
읽기 -
접근법 2: Python에서 실행하는 동안
subprocess
의stdout
을 읽기 위해 프로세스를 폴링합니다.
이 기사의 주요 목적은 Python에서 실행 중인 subprocess
의 stdout
을 읽는 방법을 보여주는 것입니다.
Python 하위 프로세스 실행 중 stdout
읽기
다른 많은 내장 모듈과 마찬가지로 Subprocess
도 “일반” Python 설치와 함께 미리 설치된 내장 모듈입니다.
새 프로세스에서 작업, 프로세스 및 프로그램을 실행하고 특정 작업 집합을 수행하고 결과를 반환하려는 경우에 주로 사용됩니다.
널리 사용되는 많은 이유 중 하나는 별도의 프로세스로 프로그램에서 직접 외부 프로그램 및 실행 파일을 실행할 수 있다는 것입니다.
Subprocess
라이브러리를 사용하여 프로그램을 실행하는 동안 해당 외부 프로그램의 출력을 실시간으로 표시해야 할 수 있습니다. 이것은 프로그램이 실시간일 수 있고 짧은 시간 후에 계산에 의존하는 경우와 같은 많은 이유로 요구 사항이 될 수 있습니다.
다음 프로그램을 고려하십시오.
import subprocess
def execute(command):
process = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
output = process.communicate()[0]
exitCode = process.returncode
if exitCode == 0:
return output
else:
raise Exception(command, exitCode, output)
if __name__ == "__main__":
print(execute("cd C:\\ && C: && tree").decode("unicode_escape"))
출력:
Folder PATH listing
Volume serial number is 0213-B7F2
C:.
+---DRIVERS
¦ +---bluetooth
¦ +---U1BLT07AVVASDSAP
¦ +---Custom
¦ ¦ +---EULA
¦ +---Win64
¦ +---LD
¦ +---svcpack
+---flutter
¦ +---.git
¦ ¦ +---hooks
¦ ¦ +---info
¦ ¦ +---logs
¦ ¦ ¦ +---refs
¦ ¦ ¦ +---heads
¦ ¦ ¦ +---remotes
¦ ¦ ¦ +---origin
¦ ¦ +---objects
¦ ¦ ¦ +---info
¦ ¦ ¦ +---pack
¦ ¦ +---refs
¦ ¦ +---heads
¦ ¦ +---remotes
¦ ¦ ¦ +---origin
¦ ¦ +---tags
¦ +---.github
¦ ¦ +---ISSUE_TEMPLATE
¦ ¦ +---workflows
¦ +---.idea
¦ ¦ +---runConfigurations
...
프로그램에서 출력을 볼 수 있지만 실시간으로는 볼 수 없습니다. 출력은 전체 명령(여기서는 tree
)이 실행을 마친 후에만 표시됩니다.
Subprocess
명령을 사용하여 별도의 프로세스에서 프로그램(또는 명령)이 실행될 때까지 출력에 무언가가 표시되지 않습니다.
우리의 경우 실시간으로 출력을 얻어야 하므로 stdout
에 기록된 프로그램의 출력을 보여주는 또 다른 솔루션을 만들어야 합니다.
솔루션은 여러 가지 방법으로 접근할 수 있으며 그 중 일부는 아래에 언급되어 있습니다.
접근법 1: Python에서 실행하는 동안 check_call
을 사용하여 subprocess
의 stdout
읽기
다음 코드를 고려하십시오.
import subprocess
import sys
def execute(command):
subprocess.check_call(
command, shell=True, stdout=sys.stdout, stderr=subprocess.STDOUT
)
if __name__ == "__main__":
print(execute("cd C:\\ && C: && tree").decode("unicode_escape"))
출력:
Folder PATH listing
Volume serial number is 0213-B7F2
C:.
├───DRIVERS
│ └───bluetooth
│ └───U1BLT0720US14CMP
│ ├───Custom
│ │ └───EULA
│ └───Win64
│ ├───LD
│ └───svcpack
├───flutter
│ ├───.git
│ │ ├───hooks
│ │ ├───info
│ │ ├───logs
│ │ │ └───refs
│ │ │ ├───heads
│ │ │ └───remotes
│ │ │ └───origin
│ │ ├───objects
│ │ │ ├───info
│ │ │ └───pack
│ │ └───refs
│ │ ├───heads
│ │ ├───remotes
│ │ │ └───origin
│ │ └───tags
│ ├───.github
│ │ ├───ISSUE_TEMPLATE
│ │ └───workflows
│ ├───.idea
│ │ └───runConfigurations
│ ├───.pub-cache
│ │ ├───hosted
│ │ │ └───pub.dartlang.org
│ │ │ ├───.cache
...
주요 요구 사항이 프로그램의 출력을 실시간으로 인쇄하는 것이라면 check_call
을 사용하여 이를 달성할 수 있습니다. 이 간단하고 깨끗하며 우아한 솔루션은 출력만 인쇄해야 하는 경우와 같이 매우 간단한 프로그램에 간결하고 “완벽"합니다.
check_call
은 매개변수 전달도 지원하므로 프로그램이 작동하기 위해 인수가 필요한 경우 번거로움 없이 함수에 쉽게 전달할 수 있습니다. 이 메서드는 프로그램이 완료될 때까지 기다립니다.
프로그램 완료에 따라 메서드가 반환됩니다. 그렇지 않으면 CalledProcessError
예외가 발생합니다. CalledProcessError
에는 returncode
특성을 사용하여 액세스할 수 있는 오류 반환 코드가 있습니다.
위에서 언급한 코드에서 command
는 실행할 명령(또는 프로그램)이 포함된 check_call
메서드로 전달됩니다.
shell
매개변수는 셸을 사용하여 프로세스를 실행하기 위해 true
로 설정되었고 프로세스의 stdout
은 우리 프로그램의 stdout
으로 설정되었으므로 stdout
에 직접 기록할 수 있습니다. stdout
에서 발생하는 변경 사항을 확인하십시오.
마지막으로 stderr
는 생성된 프로세스의 stdout
으로 설정됩니다.
접근법 2: Python에서 실행하는 동안 subprocess
의 stdout
을 읽기 위해 프로세스를 폴링합니다.
다음 코드를 고려하십시오.
import subprocess
import sys
def execute(command):
process = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
# Poll process for new output until finished
while True:
nextline = process.stdout.readline().decode("unicode_escape")
if nextline == "" and process.poll() is not None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
output = process.communicate()[0]
exitCode = process.returncode
if exitCode == 0:
return output
else:
raise Exception(command, exitCode, output)
if __name__ == "__main__":
print(execute("cd C:\\ && C: && tree").decode("unicode_escape"))
출력:
...
¦ ¦ ¦ ¦ ¦ +---UuidUtil
¦ ¦ ¦ ¦ +---example
¦ ¦ ¦ ¦ +---lib
¦ ¦ ¦ ¦ +---test
¦ ¦ ¦ +---vector_math-2.1.2
¦ ¦ ¦ ¦ +---benchmark
¦ ¦ ¦ ¦ +---bin
¦ ¦ ¦ ¦ +---lib
¦ ¦ ¦ ¦ ¦ +---src
¦ ¦ ¦ ¦ ¦ +---vector_math
¦ ¦ ¦ ¦ ¦ ¦ +---third_party
¦ ¦ ¦ ¦ ¦ +---vector_math_64
¦ ¦ ¦ ¦ ¦ ¦ +---third_party
¦ ¦ ¦ ¦ ¦ +---vector_math_geometry
¦ ¦ ¦ ¦ ¦ ¦ +---filters
¦ ¦ ¦ ¦ ¦ ¦ +---generators
¦ ¦ ¦ ¦ ¦ +---vector_math_lists
¦ ¦ ¦ ¦ ¦ +---vector_math_operations
¦ ¦ ¦ ¦ +---test
¦ ¦ ¦ ¦ +---tool
¦ ¦ ¦ +---video_player-2.2.11
¦ ¦ ¦ ¦ +---android
¦ ¦ ¦ ¦ ¦ +---gradle
...
Subprocess
를 사용하여 생성된 프로그램의 출력이 stdout
에 기록되는 즉시 인쇄되도록 하려면 출력 프로세스를 폴링하고 프로그램 stdout
의 stdout
의 마지막 줄을 계속 읽어야 합니다.
“무한” 루프에서 readline()
을 사용하여 생성된 프로세스의 출력을 계속 읽습니다. 출력이 인코딩되었으므로 적절하게 표시되도록 디코딩해야 합니다(이 경우 utf-escape
).
이는 decode
방법을 사용하고 관련 인코딩 체계를 전달하여 수행할 수 있습니다.
프로그램 실행이 완료되면 “무한” 루프도 탈출해야 합니다. 다음 두 가지를 확인하여 그렇게 할 수 있습니다.
- 현재
stdout
라인이 비어 있습니다. - 프로세스가 종료되었거나 종료되었습니다.
첫 번째 조건에 대한 간단한 문자열 비교와 프로세스가 종료되었는지 여부를 확인하는 poll()
메서드를 사용하여 매우 간단하게 수행할 수 있습니다. 프로그램이 종료되면 returncode
를 반환합니다. 그렇지 않으면 None
을 반환합니다.
None
과의 간단한 비교를 통해 프로그램 실행이 완료되었는지 여부에 대한 정보도 얻을 수 있습니다.
Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.
LinkedIn