我有一个需要执行多个命令行实用程序的python脚本。 stdout输出有时用于进一步处理。在所有情况下,我想记录结果并在检测到错误时引发异常。我使用以下函数来实现此目的:
def execute(cmd, logsink):
logsink.log("executing: %s\n" % cmd)
popen_obj = subprocess.Popen(\
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = popen_obj.communicate()
returncode = popen_obj.returncode
if (returncode <> 0):
logsink.log(" RETURN CODE: %s\n" % str(returncode))
if (len(stdout.strip()) > 0):
logsink.log(" STDOUT:\n%s\n" % stdout)
if (len(stderr.strip()) > 0):
logsink.log(" STDERR:\n%s\n" % stderr)
if (returncode <> 0):
raise Exception, "execute failed with error output:\n%s" % stderr
return stdout
“logsink”可以是任何带有log方法的python对象。我通常使用它来将日志记录数据转发到特定文件,或将其回显到控制台,或两者,或其他...
这非常好用,除了三个问题,我需要比communication()方法提供更细粒度的控制:
答案 0 :(得分:5)
如果您只想将输出放在文件中以供日后评估,则可以重定向到文件。
您已经定义了stdout = / stderr = methods执行的进程的stdout / stderr。
在您的示例代码中,您只需重定向到脚本当前out / err分配。
subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sys.stdout和sys.stderr只是文件类对象。 正如关于sys.stdout的文档文档所提到的,“任何对象都是可接受的,只要它有一个带有字符串参数的write()方法。”
f = open('cmd_fileoutput.txt', 'w')
subprocess.Popen(cmd, shell=True, stdout=f, stderr=f)
所以你只需要给它一个带有write方法的类来重定向输出。
如果您希望控制台输出和文件输出都可以创建一个类来管理输出。
一般重定向:
# Redirecting stdout and stderr to a file
f = open('log.txt', 'w')
sys.stdout = f
sys.stderr = f
制作重定向课程:
# redirecting to both
class OutputManager:
def __init__(self, filename, console):
self.f = open(filename, 'w')
self.con = console
def write(self, data):
self.con.write(data)
self.f.write(data)
new_stdout = OutputManager("log.txt", sys.stdout)
交错取决于缓冲,因此您可能会或可能不会得到您期望的输出。 (您可以关闭或减少使用的缓冲,但我现在不记得如何)
答案 1 :(得分:2)
您可以查看pexpect(http://www.noah.org/wiki/Pexpect)
它解决了1)和2)开箱即用,输出前缀可能有点棘手。
答案 2 :(得分:1)
另一个选择:
def run_test(test_cmd):
with tempfile.TemporaryFile() as cmd_out:
proc = subprocess.Popen(test_cmd, stdout=cmd_out, stderr=cmd_out)
proc.wait()
cmd_out.seek(0)
output = "".join(cmd_out.readlines())
return (proc.returncode, output)
这会根据需要将stdout
和stderr
交错显示在一个方便您打开的真实文件中。
答案 3 :(得分:1)