可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am a Python newbie writing a Python (2.7) script that needs to exec a number of external applications, one of which writes a lot of output to its stderr stream. What I am trying to figure out is a concise and succinct way (in Python) to get the last N lines from that subprocess' stderr output stream.
Currently, I am running that external application from my Python script like so:
p = subprocess.Popen('/path/to/external-app.sh', stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: print "ERROR: External app did not complete successfully (error code is " + str(p.returncode) + ")" print "Error/failure details: ", stderr status = False else: status = True
I'd like to capture the last N lines of output from its stderr stream so that they can be written to a log file or emailed, etc.
回答1:
N = 3 # for 3 lines of output p = subprocess.Popen(['/path/to/external-app.sh'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: print ("ERROR: External app did not complete successfully " "(error code is %s)" % p.returncode) print "Error/failure details: ", '\n'.join(stderr.splitlines()[-N:]) status = False else: status = True
回答2:
If the whole output can't be stored in RAM then:
import sys from collections import deque from subprocess import Popen, PIPE from threading import Thread ON_POSIX = 'posix' in sys.builtin_module_names def start_thread(func, *args): t = Thread(target=func, args=args) t.daemon = True t.start() return t def consume(infile, output): for line in iter(infile.readline, ''): output(line) infile.close() p = Popen(['cat', sys.argv[1]], stdout=PIPE, stderr=PIPE, bufsize=1, close_fds=ON_POSIX) # preserve last N lines of stdout, print stderr immediately N = 100 queue = deque(maxlen=N) threads = [start_thread(consume, *args) for args in (p.stdout, queue.append), (p.stderr, sys.stdout.write)] for t in threads: t.join() # wait for IO completion print ''.join(queue), # print last N lines retcode = p.wait()