python逐行读取子进程的输出代码
python中默认情况下是等待子进程完成之后,一下读取子进程的输出,要想逐行读取,需要自己做一点小技巧。
import sys,os,socket import datetime import fcntl import subprocess from threading import Thread def log_worker(stdout): ''' needs to be in a thread so we can read the stdout w/o blocking ''' username, hostname = os.environ.get('USER'), socket.gethostname() log_file = '/var/log/mysql-%s.log' % username log = open(log_file, 'a') while True: output = non_block_read(stdout).strip() if output: ''' [Tue Oct 30 22:13:13 2012 cseibert@host1]> ''' prompt = '[%(timestamp)s %(username)s@%(host)s]> \n' % dict( timestamp=datetime.datetime.now().strftime('%a %b %d %H:%M:%S %Y'), username=username, host=hostname) print prompt + output log.write(prompt + output + '\n') log.close() def non_block_read(output): ''' even in a thread, a normal read with block until the buffer is full ''' fd = output.fileno() fl = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) try: return output.read() except: return '' if __name__ == '__main__': sub_process = subprocess.Popen( ['sh', '/root/test/dummy.sh'], stdin=sys.stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE) thread = Thread(target=log_worker, args=[sub_process.stdout]) thread.daemon = True thread.start() sub_process.wait() thread.join(timeout=1)