我有一个命令行工具(实际上是几个),我正在用Python编写包装器。
该工具通常使用如下:
$ path_to_tool -option1 -option2 > file_out
用户将输出写入file_out,并且还可以在工具运行时查看该工具的各种状态消息。
我想复制此行为,同时还将stderr(状态消息)记录到文件中。
我拥有的是:
from subprocess import call
call(['path_to_tool','-option1','option2'], stdout = file_out, stderr = log_file)
这很好用,除了stderr没有写入屏幕。 我当然可以添加代码来将log_file的内容打印到屏幕上,但是用户将在完成所有操作后看到它,而不是在它发生时。
总结一下,期望的行为是:
我有一种感觉,我要么缺少一些非常简单的东西,要么这比我想象的要复杂得多...感谢您的帮助!
编辑:这只需要在Linux上运行。
答案 0 :(得分:1)
我认为你所寻找的是:
import sys, subprocess
p = subprocess.Popen(cmdline,
stdout=sys.stdout,
stderr=sys.stderr)
要将输出/日志写入文件,我会修改我的cmdline
以包含常用的重定向,就像在普通的linux bash / shell上完成一样。例如,我会将tee
附加到命令行:cmdline += ' | tee -a logfile.txt'
希望有所帮助。
答案 1 :(得分:1)
我必须对@ abarnert对Python 3的回答进行一些更改。这似乎有效:
def tee_pipe(pipe, f1, f2):
for line in pipe:
f1.write(line)
f2.write(line)
proc = subprocess.Popen(["/bin/echo", "hello"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# Open the output files for stdout/err in unbuffered mode.
out_file = open("stderr.log", "wb", 0)
err_file = open("stdout.log", "wb", 0)
stdout = sys.stdout
stderr = sys.stderr
# On Python3 these are wrapped with BufferedTextIO objects that we don't
# want.
if sys.version_info[0] >= 3:
stdout = stdout.buffer
stderr = stderr.buffer
# Start threads to duplicate the pipes.
out_thread = threading.Thread(target=tee_pipe,
args=(proc.stdout, out_file, stdout))
err_thread = threading.Thread(target=tee_pipe,
args=(proc.stderr, err_file, stderr))
out_thread.start()
err_thread.start()
# Wait for the command to finish.
proc.wait()
# Join the pipe threads.
out_thread.join()
err_thread.join()