将subprocess.Popen的stdout保存到文件,并向文件中写入更多内容

30 投票
4 回答
101217 浏览
提问于 2025-04-16 00:54

我正在写一个Python脚本,使用subprocess.Popen来执行两个程序(这些程序是用C语言编写的),它们都会产生输出。这个脚本会获取这些输出并保存到一个文件里。因为输出有时候会很大,导致subprocess.PIPE处理不过来,脚本就会卡住,所以我直接把输出写入日志文件。我想在文件的开头和结尾,以及两个subprocess.Popen调用之间写一些内容。但是,当我查看我的日志文件时,发现我从脚本写入的内容都集中在文件的顶部,后面跟着所有程序的输出。我该怎么把我添加的文本和文件中的内容交错在一起呢?

def run(cmd, logfile):
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile)
    return p

def runTest(path, flags, name):
    log = open(name, "w")
    print >> log, "Calling executable A"
    a_ret = run(path + "executable_a_name" + flags, log)
    print >> log, "Calling executable B"
    b_ret = run(path + "executable_b_name" + flags, log)
    print >> log, "More stuff"
    log.close()

日志文件的内容是: 调用可执行文件A 调用可执行文件B 更多内容 [... 两个可执行文件的输出 ...]

有没有办法在调用Popen后,把A的输出立即写入日志文件呢?还有一个可能相关的事情:可执行文件A开始后会等待B,等B打印完内容并结束后,A再打印更多内容并结束。

我在RHE Linux上使用Python 2.4。

4 个回答

2

我觉得就保持简单明了就好。下面是伪代码的基本逻辑:

write your start messages to logA
execute A with output to logA
write your in-between messages to logB
execute B with output to logB
write your final messages to logB
when A & B finish, write content of logB to the end of logA
delete logB
3

你需要等这个过程完成了才能继续。 我还把代码改成了使用上下文管理器,这样看起来更简洁。

def run(cmd, logfile):
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile)
    p.wait()
    return p

def runTest(path, flags, name):
    with open(name, "w") as log:
        print >> log, "Calling executable A"
        a_ret = run(path + "executable_a_name" + flags, log)
        print >> log, "Calling executable B"
        b_ret = run(path + "executable_b_name" + flags, log)
        print >> log, "More stuff"
28

你可以对每个 Popen 对象调用 .wait(),这样可以确保它们都已经完成,然后再调用 log.flush()。大概可以这样做:

def run(cmd, logfile):
    p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=logfile)
    ret_code = p.wait()
    logfile.flush()
    return ret_code

如果你需要在外部函数中与 Popen 对象进行交互,可以把 .wait() 的调用移到外部函数中去。

撰写回答