관리 메뉴

개발자비행일지

python subprocess 모듈, .communicate() 본문

▶ Python

python subprocess 모듈, .communicate()

Cyber0946 2020. 7. 22. 16:16
  • 파이썬으로 외부 명령어 실행
  • 파이썬으로 외부 명령어를 실행하는 방법은 subprocess 모듈을 사용해서 실행한다. 
subprocess.Popen() 이 함수는 로컬 프로그램, 명령어를 사용한다. Popen을 통해서 shell 명령어를 전달 할 수도 있는데 이를 위해서는 인자값을 True로 설정해 주어야 한다. 
#!/usr/bin/python
# -*- coding: utf-8 -*-
import subprocess
import shlex

# 문자열 명령어 실행
def subprocess_open(command):
    popen = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    (stdoutdata, stderrdata) = popen.communicate()
    return stdoutdata, stderrdata

# 배치 파일 등 실행
def subprocess_open_when_shell_false(command):
    popen = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (stdoutdata, stderrdata) = popen.communicate()
    return stdoutdata, stderrdata

# 문자열 명령어 실행
# shell 변수를 false 로 줄경우(default가 false) 명령어를 shelx.split() 함수로 프로세스가 인식 가능하게 잘라 주어야 함
def subprocess_open_when_shell_false_with_shelx(command):
    popen = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (stdoutdata, stderrdata) = popen.communicate()
    return stdoutdata, stderrdata

# 커맨드 리스트 처리
# 커맨드 리스트를 이전 처리의 결과(stdout)를 다음 처리의 입력(stdin)으로 입력하여 순차적으로 처리
def subprocess_pipe(cmd_list):
    prev_stdin = None
    last_p = None
    
    for str_cmd in cmd_list:
        cmd = str_cmd.split()
        last_p = subprocess.Popen(cmd, stdin=prev_stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        prev_stdin = last_p.stdout
    
    (stdoutdata, stderrdata) = last_p.communicate()
    return stdoutdata, stderrdata


def main():
    print subprocess_open('echo "aaa" | wc -l > a.txt')
    # 실행결과
    # --> ('', '') 파일 a.txt 생성
    
    print subprocess_open_when_shell_false("./test.sh")
    # test.sh
    # #!/bin/bash
    # echo "aaa" | wc -l > b.txt
    # 실행결과
    # --> ('', '') 파일 b.txt 생성
    
    print subprocess_open_when_shell_false_with_shelx('echo -n "aaa"')
    # 실행결과
    # ('aaa', '')
    
    print subprocess_open_when_shell_false_with_shelx('echo "aaa" | wc -l')
    # 실행결과
    # ('aaa | wc -l\n', '')
    
    print subprocess_pipe(['echo "aaa"', "wc -l"])
    # 실행결과
    # ('1\n', '')
    
if __name__ == "__main__":
    main()       

subprocess 모듈

  • 예제
    • Popen 생성자: 프로세스를 시작
    • communicate 메서드: 자식 프로세스의 출력을 읽어옴, 자식 프로세스가 종료할 때까지 대기
import subprocess
proc= subprocess.Popen(["echo", "Hello form the child!!"], stdout =subprocess.PIPE)
out, err = proc.communicate()
print(out.decode("utf-8"))

>>>Hello form the child!

  • 자식 프로세스는 부모 프로세스와 파이썬 인터프리터와는 독립적으로 실행
  • 자식 프로세스의 상태는 파이썬이 다른 작업을 하는 동안 주기적으로 폴링(polling)됨
import subprocess
proc= subprocess.Popen(["sleep", "0.3")
while proc.poll() is None:
	print("working")
    print(proc.poll()
print("Exit status", proc.poll())

>>> Working...

Working...

Exit status 0

  • 부모에서 자식 프로세스를 떼어냄 => 부모 프로세스가 자유롭게 여러 자식 프로세스를 병렬로 실행할 수 있음
  • 자식 프로세스를 떼어내려면?
    • 모든 자식 프로세스를 먼저 시작하면 됨