2010-07-06 4 views
16

나는 stdout을 생성하는 두 개의 프로그램 (컴파일 된 C 코드)을 실행하기 위해 subprocess.Popen을 사용하는 파이썬 스크립트를 작성하고 있습니다. 스크립트는 해당 출력을 가져 와서 파일에 저장합니다. 때때로 출력이 subprocess.PIPE를 압도하기에 충분히 커서 스크립트가 멈추기 때문에 stdout을 로그 파일에 직접 보냅니다. 내 스크립트는 파일의 처음과 끝에 그리고 두 개의 하위 프로세스 사이에 무언가를 쓰게하고 싶다 .Popen 호출. 그러나 로그 파일을 볼 때 스크립트에서 로그 파일에 기록한 모든 내용이 모두 파일 맨 위에 함께 표시되고 모든 실행 가능 표준 출력이 이어집니다. 추가 된 텍스트를 어떻게 파일에 삽입 할 수 있습니까?서브 프로세스에서 stdout 저장. 파일을 열거 나 더 많은 내용을 파일에 더하기

def run(cmd, logfile): 
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile) 
    return p 

def runTest(path, flags, name): 
    log = open(name, "w") 
    print >> log, "Calling executable A" 
    a_ret = run(path + "executable_a_name" + flags, log) 
    print >> log, "Calling executable B" 
    b_ret = run(path + "executable_b_name" + flags, log) 
    print >> log, "More stuff" 
    log.close() 

로그 파일이 있습니다 : 실행 B 를 호출 실행 호출 더 많은 물건 [... 모두 실행 파일에서 표준 출력 ...]

I가 A의 표준 출력을 세척 할 수있는 방법이 있나요 Popen을 호출 한 후의 로그? 관련성이있는 한 가지 더 : 실행 가능한 A 시작은 B에서 시작되고 B가 물건을 인쇄하고 끝내면 A가 더 많은 내용을 인쇄하고 끝납니다.

저는 RHE Linux에서 Python 2.4를 사용하고 있습니다.

+0

stdout = subprocess.PIPE를 사용하고 외부 루프에서 로그 파일에 모든 내용을 쓰게되면 내 텍스트를 실행 파일의 출력으로 인터리브 할 수있었습니다. 텍스트를 추가하지 않으면 로그에 다음 순서로 내용이 있습니다. 1) 출력 2) B 출력 3) 나머지 A 출력. 나는 그 단계들의 앞이나 뒤에 각각 텍스트를 추가 할 수있었습니다. 이제는 로그의 시작 또는 끝에 텍스트 만 추가 할 수 있습니다. A가 B에서 핸드 셰이크를 기다리기 때문에 A가 끝날 때까지 B가 시작되지 않기 때문에 Popen이 스크립트를 정지시킨 후 wait()를 추가합니다.이 방법으로 로그에 내 텍스트를 삽입 할 수 있습니까? – jasper77

답변

15

각 Popen 객체에서 .wait()를 호출하여 작업이 완료되었는지 확인한 다음 log.flush()를 호출 할 수 있습니다. 이 같은 아마 뭔가 :

def run(cmd, logfile): 
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile) 
    ret_code = p.wait() 
    logfile.flush() 
    return ret_code 

당신이 .wait을 움직일 수 귀하의 외부 함수에서는 popen 개체와 상호 작용해야하는 경우() 대신에이 호출합니다.

+1

run() 함수에 wait()를 넣으면 A가 끝날 때까지 실행 파일 B가 실행되지 않고 B가 끝날 때까지 A가 완료되지 않으므로 스크립트가 중단됩니다. 그러나 runTest(), 외부 함수, A, B 실행 한 다음 A 기다리고 로그 플러시, runTest 끝에 인쇄 할 줄 실제로 로그 파일의 끝에 나타나는지 발견했습니다. B가 실행되기 바로 전에 파일에 텍스트를 인쇄하는 방법을 찾지 못했습니다. 나는 방법이 있다는 것을 모른다. – jasper77

+2

'logfile.flush()'는 자식 프로세스에 영향을주지 않습니다. – jfs

1

계속하기 전에 프로세스가 완료 될 때까지 기다려야합니다. 또한 컨텍스트 관리자를 사용하도록 코드를 변환했으며, 이는 더 깨끗합니다.

def run(cmd, logfile): 
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile) 
    p.wait() 
    return p 

def runTest(path, flags, name): 
    with open(name, "w") as log: 
     print >> log, "Calling executable A" 
     a_ret = run(path + "executable_a_name" + flags, log) 
     print >> log, "Calling executable B" 
     b_ret = run(path + "executable_b_name" + flags, log) 
     print >> log, "More stuff" 
+0

컨텍스트 관리자는 여전히 RHEL5 시스템을 실행하는 사람이 사용할 수없는 python2.6 기능입니다. RHEL6이 나오기 전까지는 사용하지 않는 것이 가장 좋습니다. – Jerub

+0

다른 가져 오기보다'from __future__ import with_statement'를 사용하여 파이썬 2.5에서 컨텍스트 관리자를 사용할 수 있습니다. – detly

+0

하지만 RHEL5가 Python 2.4에 고정되어있는 것처럼 보입니다. –

2

나는 간단하게 말합니다. 의사 코드를 기본 논리 : 만 B 종료 후에는 것이나 A 종료 할 B에 대한 A 프로그램 대기를 알고있는 것처럼

write your start messages to logA 
execute A with output to logA 
write your in-between messages to logB 
execute B with output to logB 
write your final messages to logB 
when A & B finish, write content of logB to the end of logA 
delete logB 
+0

단일 로그 파일 대신 A와 B에 대해 두 개의 개별 로그 파일을 사용하는 사고 - 밖에서 제안 해 주셔서 감사합니다. 나는 그것에 대해 생각해야 할 것이다. – jasper77

1

.

B 경우에 당신은 역순으로 프로세스를 시작할 수 있습니다 실행 A없이 시작할 수 있습니다

from os.path import join as pjoin 
from subprocess import Popen 

def run_async(cmd, logfile): 
    print >>log, "calling", cmd 
    p = Popen(cmd, stdout=logfile) 
    print >>log, "started", cmd 
    return p 

def runTest(path, flags, name): 
    log = open(name, "w", 1) # line-buffered 
    print >>log, 'calling both processes' 
    pb = run_async([pjoin(path, "executable_b_name")] + flags.split(), log) 
    pa = run_async([pjoin(path, "executable_a_name")] + flags.split(), log) 
    print >>log, 'started both processes' 
    pb.wait() 
    print >>log, 'process B ended' 
    pa.wait() 
    print >>log, 'process A ended' 
    log.close() 

참고 : 주요 공정 log.flush()를 호출하면 자식 프로세스의 파일 버퍼에 영향을주지 않습니다.

자식 프로세스가 stdout에 대해 블록 버퍼링을 사용하는 경우 pexpect, pty, or stdbuf을 사용하여 더 빨리 플러시하도록 할 수 있습니다 (대화식으로 실행되거나 I/O 용 C stdio 라이브러리를 사용하는 경우 프로세스가 라인 버퍼링을 사용한다고 가정 함).