【问题标题】:Piping output of subprocess.Popen to filessubprocess.Popen 的管道输出到文件
【发布时间】:2011-01-20 20:10:37
【问题描述】:

我需要使用subprocess.Popen 启动多个长时间运行的进程,并希望每个进程中的stdoutstderr 自动通过管道传输到单独的日志文件。每个进程将同时运行几分钟,我希望在进程运行时写入两个日志文件(stdoutstderr每个进程

我是否需要在循环中对每个进程不断调用p.communicate() 以更新每个日志文件,或者是否有某种方法可以调用原始Popen 命令以便stdoutstderr 自动流式传输到打开文件句柄?

【问题讨论】:

    标签: python subprocess stdout


    【解决方案1】:

    您可以将stdoutstderr 作为参数传递给Popen()

    subprocess.Popen(self, args, bufsize=0, executable=None, stdin=None, stdout=None,
                     stderr=None, preexec_fn=None, close_fds=False, shell=False,
                     cwd=None, env=None, universal_newlines=False, startupinfo=None, 
                     creationflags=0)
    

    例如

    >>> import subprocess
    >>> with open("stdout.txt","wb") as out, open("stderr.txt","wb") as err:
    ...    subprocess.Popen("ls",stdout=out,stderr=err)
    ... 
    <subprocess.Popen object at 0xa3519ec>
    >>> 
    

    【讨论】:

    • 哇!我不知道你可以在上下文管理器中像这样链接opens。 #头脑风暴
    • 对我不起作用! with open("server.log", "wb") as out: sp.call(server_cmd, stdout = out)
    • 为什么必须是“wb”?有没有强制输出为 unicode?​​span>
    • 你可以像 open("abc.txt","wb",encoding="utf-8") as file_object 一样使用 open("abc.txt","wb",encoding="utf-8") as file_object 的 encode 参数
    • 这些文件句柄的有效期是多久?如果with 范围关闭,但子进程仍在运行,那么文件句柄在子进程终止之前是否保持有效?然后它们会自动关闭吗?
    【解决方案2】:

    the docs

    stdin、stdout 和 stderr 指定 执行程序的标准输入, 标准输出和标准错误 文件句柄,分别。有效的 值是 PIPE,一个现有文件 描述符(一个正整数),一个 现有文件对象和无。

    所以只需将可写入的文件对象作为命名参数stdout=stderr= 传递就可以了!

    【讨论】:

    • 谢谢。我本可以发誓我之前尝试过但出现错误,但这正是我希望的工作。
    • 这对我不起作用。我同时运行两个进程并将 stdout 和 stderr 从两者保存到一个日志文件中。如果输出太大,则其中一个子进程挂起;不知道是哪个。我不能在评论中使用格式,所以我会在下面附加一个“答案”。
    【解决方案3】:

    我同时运行两个子进程,并将两个子进程的输出保存到一个日志文件中。我还建立了一个超时来处理挂起的子进程。当输出太大时,总是会触发超时,并且任何一个子进程的标准输出都不会保存到日志文件中。上面Alex提出的答案并没有解决。

    # Currently open log file.
    log = None
    
    # If we send stdout to subprocess.PIPE, the tests with lots of output fill up the pipe and
    # make the script hang. So, write the subprocess's stdout directly to the log file.
    def run(cmd, logfile):
       #print os.getcwd()
       #print ("Running test: %s" % cmd)
       global log
       p = subprocess.Popen(cmd, shell=True, universal_newlines = True, stderr=subprocess.STDOUT, stdout=logfile)
       log = logfile
       return p
    
    
    # To make a subprocess capable of timing out
    class Alarm(Exception):
       pass
    
    def alarm_handler(signum, frame):
       log.flush()
       raise Alarm
    
    
    ####
    ## This function runs a given command with the given flags, and records the
    ## results in a log file. 
    ####
    def runTest(cmd_path, flags, name):
    
      log = open(name, 'w')
    
      print >> log, "header"
      log.flush()
    
      cmd1_ret = run(cmd_path + "command1 " + flags, log)
      log.flush()
      cmd2_ret = run(cmd_path + "command2", log)
      #log.flush()
      sys.stdout.flush()
    
      start_timer = time.time()  # time how long this took to finish
    
      signal.signal(signal.SIGALRM, alarm_handler)
      signal.alarm(5)  #seconds
    
      try:
        cmd1_ret.communicate()
    
      except Alarm:
        print "myScript.py: Oops, taking too long!"
        kill_string = ("kill -9 %d" % cmd1_ret.pid)
        os.system(kill_string)
        kill_string = ("kill -9 %d" % cmd2_ret.pid)
        os.system(kill_string)
        #sys.exit()
    
      end_timer = time.time()
      print >> log, "closing message"
    
      log.close()
    

    【讨论】:

    • shell=True 不建议使用
    猜你喜欢
    • 2013-05-25
    • 2011-11-15
    • 2017-07-11
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多