2011-10-04 8 views
4

실제 파이썬 버전을 time 명령 줄 프로그램으로 작성하려고합니다. 실제/usr/sys 시간을 셸에 표시하는 대신 데이터베이스에 기록합니다.파이썬 셸 래퍼

내가 현재 가지고하는 것은 :

wrapper.py

#!/usr/bin/python 
import sys 
from subprocess import Popen, PIPE 
cmd = 'time ' + (' '.join(['"%s"' % v if ' ' in v else v for v in sys.argv[1:]])) 
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) 
print p.stdout.read() 
print p.stderr.read() 

단순화를 들어, 나는 데이터베이스 삽입 코드를 제외했습니다.

그러나, 문제를 설명하기 위해, 나는 테스트 스크립트 사용하고 있습니다 : 나는 wrapper.py python delay.py을 실행하면

#!/usr/bin/python 
import time 
for i in xrange(3): 
    print i 
    time.sleep(1) 

, 나는 초이 같은 다음, 실시간으로 인쇄보고 싶습니다를 :

real 0m3.057s 
user 0m0.030s 
sys 0m0.000s 

는 대신, 3 초 동안 아무 출력을 얻을 수없고, 다음이 인쇄되어 있습니다 :

0 
1 
2 

0.02user 0.00system 0:03.03elapsed 0%CPU (0avgtext+0avgdata 21632maxresident)k 
0inputs+0outputs (0major+1514minor)pagefaults 0swaps 

서브 프로세스의 출력을 실시간으로 어떻게 읽고 출력합니까?

time의 출력은 왜 내가 쉘에서 직접 실행하고 파이썬 스크립트 내의 서브 프로세스에서 실행될 때 뒤죽박죽이되는 것과 다른가요?

답변

2

첫째, 당신은 왜 모든 파이썬과 I/O를 처리하는? 하위 프로세스의 stdout과 stderr가 파이썬과 동일한 위치로 이동하게하십시오. 둘째, 실제로 time 명령을 사용하는 대신 파이썬에서 직접 자원을 검색 할 수 있습니다. 다음과 같이 시도하십시오.

#! /usr/bin/python 

import os 
import resource 
import sys 
import time 

cmd = ' '.join(sys.argv[1:]) 
stime = time.time() 
os.system(cmd)   # fire off the command 
etime = time.time() 

# now get the resource utilization 
r = resource.getrusage(resource.RUSAGE_CHILDREN) 
user_time = r.ru_utime 
sys_time = r.ru_stime 
# resource doesn't know "clock" time, so we'll just figure that ourselves 
real_time = etime - stime 

print "real\t" + str(real_time) 
print "user\t" + str(user_time) 
print "sys\t" + str(sys_time) 

이렇게하면 시간이 초 단위로 인쇄됩니다. 정말로 시간 명령과 똑같이 보이게하려면 적절하게 형식을 지정할 수 있습니다.

질문의 두 번째 부분에 대답하려면 실제로 "시간"명령이 다릅니다. 파이썬의 자식으로 실행할 때,/usr/bin/time의 출력을 얻게됩니다. 손으로 직접 실행하면 쉘의 내장 된 버전을 얻게됩니다. 쉘 프롬프트에서 "type -a time"을 입력 해보십시오. 또한 "/ usr/bin/time ./test.py"와 같이 테스트 프로그램을 실행하면 두 번째 폼이 보일 것입니다.

+0

전화하세요. 완벽하게 작동하며 예상했던 것보다 훨씬 간단합니다. – Cerin

0

당신은 실시간으로 출력을 작성해야합니다 :

process = subprocess.Popen(shlex.split(command), stdout = subprocess.PIPE, stderr = subprocess.STDOUT) 

while True: 
    output = process.stdout.read(1) 

    if output == '' and process.poll() != None: 
    break 

    if output != '': 
    sys.stdout.write(output) 
    sys.stdout.flush() 
+0

이것은 작동하지 않습니다. 여전히 블록화되어, 모든 것을 한 번에 인쇄하기 전에 하위 프로세스가 끝날 때까지 기다립니다. – Cerin