맨땅에 헤딩하는 사람

[Python] subprocess에서 stdout 실시간 출력하기 본문

파이썬/이론

[Python] subprocess에서 stdout 실시간 출력하기

purplechip 2020. 4. 23. 14:35

국내 증권사 api는 많은 데이터를 요청할 경우

제약조건(일정 시간동안 일정 횟수 이상의 조회 요청 시 조회 제한)으로 인해 가동중인 프로그램을 종료했다가 다시 실행해야 한다.

 

이에 따라 subprocess를 사용해야 하는데, 진행상황을 확인하기 위해 subprocess로 구동중인 프로그램의 콘솔 출력창을 확인해야 할 일이 생겼다. 

 

먼저, subprocess를 동작시키는 함수를 보면 다음과 같다.

 

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None,  startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False,
pass_fds=(), *, encoding=None, errors=None, text=None)

subprocess.run 함수의 경우 위 함수를 단순화시킨 것이므로 사용하고싶은 것을 사용하면 된다.

 

stdin, stdout, stderr가 외부 프로그램의 표준입력, 표준출력, 표준에러출력으로

subprocess.PIPE를 할당해주면 subprocess를 실행시키는 프로그램의 표준입출력으로 연동된다.

 

그 외 parameter는 파이썬 subprocess documentation을 참조바란다.

 

코드는 다음과 같다.

 

import subprocess

cmd_reculsive = [sys.executable, '-u', 'make_db.py', '-r']    
    
p = subprocess.Popen(cmd_reculsive,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT,
                     universal_newlines=True)
                     
while p.poll() == None:
	out = p.stdout.readline()
	print(out, end='')

cmd_reculsive

  • 실행시키고자 하는 프로세스
  • '-u' 옵션이 반드시 들어가야 한다. 없으면 프로그램이 종료된 후 한번에 stdout이 출력된다.  

stdout

  • subprocess.PIPE로 설정

stderr

  • subprocess.STDOUT으로 설정 (stdout으로 같이 보기 위함)

universal_newlines

  • False의 경우 binary, True의 경우 text로 file object가 열림

subprocess.poll()

  • child process가 종료되었는지 확인하는 함수
  • 종료되었으면 해당 프로세스의 리턴코드를 반환

subprocess.stdout.readline()

  • stdout의 출력을 읽음

 

subprocess의 경우 병렬적으로 프로세스가 수행되기 때문에, 부모프로세스, 자식프로세스가 동시에 돌아가므로 반복문을 통해 자식프로세스의 종료 여부를 확인하고, 자식프로세스의 stdout을 받아 출력한다.

 

 

+ 사족

python 실행 시 -u 옵션이 궁금하여 직접 찾아보았다.

파이썬 doc에서 나온 내용은 다음과 같다.

 

-u
stdout 과 stderr 스트림을 버퍼링하지 않도록 만듭니다. 이 옵션은 stdin 스트림에는 영향을 미치지 않습니다.
PYTHONUNBUFFERED 도 참조하세요.
버전 3.7에서 변경: stdout 과 stderr 스트림의 텍스트 계층은 이제 버퍼링 되지 않습니다.

위 설명을 보면 stdout 버퍼링때문에 출력이 안되는 것으로 생각되지만,

난 3.7 버전을 사용한다... 결국 넣으나, 안넣으나 차이는 없어야될텐데 차이가 생기는 이유가 궁금하다.

 

참고 URL 

https://docs.python.org/ko/3/using/cmdline.html

https://docs.python.org/3/library/subprocess.html

Comments