首页 文章

将stdout从subprocess.Popen保存到文件,再将更多内容写入文件

提问于
浏览
19

我正在编写一个python脚本,它使用subprocess.Popen来执行两个程序(来自编译的C代码),每个程序都生成stdout . 该脚本获取该输出并将其保存到文件中 . 因为输出有时足以压倒subprocess.PIPE,导致脚本挂起,所以我将stdout直接发送到日志文件 . 我想让我的脚本写一些文件的开头和结尾,以及两个subprocess.Popen调用之间 . 但是,当我查看我的日志文件时,我从脚本写入日志文件的所有内容都在文件顶部,然后是所有可执行文件stdout . 如何将添加的文本交错到文件?

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的stdout刷新到日志中?还有一件事可能是相关的:可执行A开始然后在B上,并且在B打印完成后,A然后打印更多东西并完成 .

我在RHE Linux上使用Python 2.4 .

4 回答

  • 2

    您可以在每个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()调用移到那里 .

  • 18

    您需要等到该过程完成后再继续 . 我还将代码转换为使用上下文管理器,它更干净 .

    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"
    
  • 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
    
  • 2

    据我了解 A 程序等待 B 做它的事情 A 退出后才 B 退出 .

    如果 B 可以在没有运行 A 的情况下启动,那么您可以按相反的顺序启动进程:

    from os.path import join as pjoin
    from subprocess import Popen
    
    def run_async(cmd, logfile):
        print >>log, "calling", cmd
        p = Popen(cmd, stdout=logfile)
        print >>log, "started", cmd
        return p
    
    def runTest(path, flags, name):
        log = open(name, "w", 1)  # line-buffered
        print >>log, 'calling both processes'
        pb = run_async([pjoin(path, "executable_b_name")] + flags.split(), log)
        pa = run_async([pjoin(path, "executable_a_name")] + flags.split(), log)
        print >>log, 'started both processes'
        pb.wait()
        print >>log, 'process B ended'
        pa.wait()
        print >>log, 'process A ended'
        log.close()
    

    注意:在主进程中调用 log.flush() 对子进程中的文件缓冲区没有影响 .

    如果子进程对stdout使用块缓冲,那么你可以尝试使用pexpect, pty, or stdbuf强制它们更快地刷新(它假设进程使用行缓冲,如果交互运行或者它们使用C stdio库进行I / O) .

相关问题