2017-03-02 12 views
2

실행중인 프로세스의 stdout을 정기적으로 확인해야하는 경우. 예를 들어, 프로세스는 tail -f /tmp/file이며 파이썬 스크립트에서 생성됩니다. 그런 다음 x 초마다 해당 하위 프로세스의 stdout이 문자열에 쓰여지고 처리됩니다. 서브 프로세스는 결국 스크립트에 의해 중지됩니다.Python에서 실행중인 하위 프로세스의 표준 출력을 확인하십시오.

지금까지 check_output (사용 된 경우) 프로세스가 여전히 실행 중이며 명확한 출력을 생성하지 않기 때문에 작동하지 않는 것처럼 보일 경우 하위 프로세스의 stdout을 구문 분석합니다.

>>> from subprocess import check_output 
>>> out = check_output(["tail", "-f", "/tmp/file"]) 
#(waiting for tail to finish) 

이 여러 하위 프로세스의 출력은 (예를 들어, 꼬리 -f/TMP/FILE1 꼬리 -f/TMP/파일 2)을 처리 할 수 ​​있도록 구성 프로세스에 대한 스레드를 사용할 수 있어야한다.

하위 프로세스를 시작하고 주기적으로 stdout을 확인 및 처리하고 결국 멀티 스레딩 방식으로 하위 프로세스를 중지 할 수 있습니까? python 스크립트는 Linux 시스템에서 실행됩니다.

목표는 파일을 계속 읽지 않는 것이고 tail 명령은 사용 된 실제 명령과 똑같이 작동하므로 예제입니다.

편집 : 나는 이것을 통해 파일이 존재하지 않는다고 생각했습니다. check_output은 이제 프로세스가 끝날 때까지 기다립니다.

EDIT2

: Popen과 함께 PIPE 다른 방법은, 동일한 문제가 발생할 것으로 보인다. tail이 완료 될 때까지 기다립니다.

>>> from subprocess import Popen, PIPE, STDOUT 
>>> cmd = 'tail -f /tmp/file' 
>>> p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) 
>>> output = p.stdout.read() 
#(waiting for tail to finish) 
+0

http://stackoverflow.com/a/6482200/1866177은 아마도이 문제를 해결합니다. – Dschoni

+1

예제는 stdout을 읽을 수없는 것보다 더 큰 문제가 있습니다. 고쳐주세요. –

+0

@Dschoni, OP가 출력을 리디렉션하지 않고 가져 오려고합니다. 이것은 당신이 제공 한 링크보다 조금 더 완성되었습니다. –

답변

4

두 번째 시도는 90 %입니다. 유일한 문제는 모두tail의 stdout이 끝나면 동시에 읽으려고한다는 것입니다. 그러나 tail는 (? 무기한) 백그라운드에서 실행하기위한 것입니다, 그래서 당신은 정말 라인별로 그것에서 표준 출력 읽고 싶어 : 나는 shell=Trueclose_fds=True 인수를 제거한

from subprocess import Popen, PIPE, STDOUT 
p = Popen(["tail", "-f", "/tmp/file"], stdin=PIPE, stdout=PIPE, stderr=STDOUT) 
for line in p.stdout: 
    print(line) 

. 첫 번째 매개 변수는 불필요하고 잠재적으로 위험하지만 두 번째 매개 변수는 기본값입니다.

파일 객체는 파이썬에서 라인을 통해 반복 가능하다는 것을 기억하십시오. for 루프는 tail 다이가 될 때까지 실행되지만 tail이 종료 될 때까지 차단되는 read과는 반대로 표시된 각 라인을 처리합니다.

/tmp/file에 빈 파일을 만들고이 프로그램을 시작하고 다른 쉘을 사용하여 파일에 줄을 반주하면 프로그램에서 해당 줄을 표시합니다. 아마도 print을 좀 더 유용한 것으로 대체해야합니다.

명령 줄

$ echo a > /tmp/file 
$ echo b > /tmp/file 
$ echo c >> /tmp/file 

프로그램 출력 (파이썬에서를 다른 쉘에서)

b'a\n' 
b'tail: /tmp/file: file truncated\n' 
b'b\n' 
b'c\n' 
을 : 여기

내가 위의 코드를 실행 한 후 입력 된 명령의 예입니다

당신이 응원하는 동안 당신의 메인 프로그램이 반응하기를 원하는 경우 연못을 tail의 출력에 연결하려면 별도의 스레드에서 루프를 시작하십시오. tail이 끝나지 않아도 프로그램이 종료되지 않도록이 스레드를 데몬으로 만들어야합니다. 스레드가 하위 프로세스를 열도록 만들거나 표준 출력을 전달할 수 있습니다.

def deal_with_stdout(): 
    for line in p.stdout: 
     print(line) 

from subprocess import Popen, PIPE, STDOUT 
from threading import Thread 
p = Popen(["tail", "-f", "/tmp/file"], stdin=PIPE, stdout=PIPE, stderr=STDOUT) 
t = Thread(target=deal_with_stdout, daemon=True) 
t.start() 
t.join() 

여기 코드는 새로운 스레드의 추가와 함께, 거의 동일합니다 : 그것은 메인 스레드에 더 많은 제어 할 수 있기 때문에 나는 후자의 접근 방식을 선호합니다. 나는 join()을 끝에 추가하여 프로그램이 예제처럼 잘 동작 할 것입니다 (join은 스레드가 돌아 오기 전에 죽을 때까지 기다립니다). 일반적으로 실행중인 처리 코드로 대체하려고합니다.

스레드가 복잡하면 target을 전달하는 대신 Thread에서 상속하고 run 메서드를 무시할 수 있습니다.

+0

잘 설명해 주셔서 감사합니다. 제게 많은 도움이됩니다! –

+1

나는 그것이 기쁘다. 멀티 스레딩과 멀티 프로세싱은 일단 사용법을 알게되면 상당히 쉬운 도구이지만 상당히 뛰어나지는 않습니다. 나를위한 최악의 부분은 용어였습니다. –