同时读取子进程的 stdout 和 stderr

2024-02-04

我正在尝试在 Python 中运行一个冗长的命令,输出到 stdout 和 stderr。我想轮询子进程并将输出写入单独的文件。

根据这个答案,我尝试了以下操作python 中 subprocess.PIPE 的非阻塞读取 https://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in-python

import subprocess

from Queue import Queue, Empty
from threading import Thread

def send_cmd(cmd, shell=False):
    """
    Send cmd to the shell
    """
    if not isinstance(cmd, list): cmd = shlex.split(cmd)

    params = {'args'   : cmd,
              'stdout' : subprocess.PIPE,
              'stderr' : subprocess.PIPE,
              'shell'  : shell}

    proc = subprocess.Popen(**params)

    return proc

def monitor_command(process, stdout_log=os.devnull, stderr_log=os.devnull):
    """
    Monitor the process that is running, and log it if desired
    """
    def enqueue_output(out, queue):
        for line in iter(out.readline, b''):
            queue.put(line)

    def setup_process(log_name, proc):
        FID = open(log_name, 'w')
        queue = Queue()
        thread = Thread(target=enqueue_output, args=(proc, queue))
        thread.daemon = True # Thread dies with program
        thread.start()

        return (queue, FID)

    def check_queues(queue_list, errors):
        for queue, FID in queue_list:
            try:
                line = queue.get_nowait()
                if 'error' in line.lower() or 'failed' in line.lower():
                    errors.append(line)
            except Empty:
                pass
            else:
                FID.write(line)

    errors = []
    queue_list = []

    for log, proc in [(stdout_log, process.stdout), (stderr_log, process.stderr)]:
        queue_list.append(setup_process(log, proc)

    while process.poll() is None:
        check_queues(queue_list, errors)

    while not queue_list[0][0].empty() or queue_list[1][0].empty():
        check_queues(queue_list, errors)

    for queue, FID in queue_list:
        FID.close()

return errors

process = send_cmd('long_program.exe')
errors  = monitor_command(process, stdout_log='stdout.log', stderr_log='stderr.log')

但如果 stdout 的输出文件是空的,而 stderr 的输出文件只有几行长,而两者都应该很大。

我缺少什么?


我这样做过一次..这是我写的一些旧代码



class Process_Communicator():

    def join(self):
        self.te.join()
        self.to.join()
        self.running = False
        self.aggregator.join()
        self.ti.join()

    def enqueue_in(self):
        while self.running and self.p.stdin is not None:
            while not self.stdin_queue.empty():
                s = self.stdin_queue.get()
                self.p.stdin.write(str(s) + '\n\r')
            pass

    def enqueue_output(self):
        if not self.p.stdout or self.p.stdout.closed:
            return
        out = self.p.stdout
        for line in iter(out.readline, b''):
            self.qo.put(line)
        #    out.flush()

    def enqueue_err(self):
        if not self.p.stderr or self.p.stderr.closed:
            return
        err = self.p.stderr
        for line in iter(err.readline, b''):
            self.qe.put(line)

    def aggregate(self):
        while (self.running):
            self.update()
        self.update()

    def update(self):
        line = ""
        try:
            while self.qe.not_empty:
                line = self.qe.get_nowait()  # or q.get(timeout=.1)
                self.unbblocked_err += line
        except Queue.Empty:
            pass

        line = ""
        try:
            while self.qo.not_empty:
                line = self.qo.get_nowait()  # or q.get(timeout=.1)
                self.unbblocked_out += line
        except Queue.Empty:
            pass

        while not self.stdin_queue.empty():
                s = self.stdin_queue.get()
                self.p.stdin.write(str(s))

    def get_stdout(self, clear=True):
        ret = self.unbblocked_out
        if clear:
            self.unbblocked_out = ""
        return ret

    def has_stdout(self):
        ret = self.get_stdout(False)
        if ret == '':
            return None
        else:
            return ret

    def get_stderr(self, clear=True):
        ret = self.unbblocked_out
        if clear:
            self.unbblocked_out = ""
        return ret

    def has_stderr(self):
        ret = self.get_stdout(False)
        if ret == '':
            return None
        else:
            return ret

    def __init__(self, subp):
        '''This is a simple class that collects and aggregates the
        output from a subprocess so that you can more reliably use
        the class without having to block for subprocess.communicate.'''
        self.p = subp
        self.unbblocked_out = ""
        self.unbblocked_err = ""
        self.running = True
        self.qo = Queue.Queue()
        self.to = threading.Thread(name="out_read",
                                    target=self.enqueue_output,
                                    args=())
        self.to.daemon = True  # thread dies with the program
        self.to.start()

        self.qe = Queue.Queue()
        self.te = threading.Thread(name="err_read",
                                   target=self.enqueue_err,
                                   args=())
        self.te.daemon = True  # thread dies with the program
        self.te.start()

        self.stdin_queue = Queue.Queue()
        self.aggregator = threading.Thread(name="aggregate",
                                           target=self.aggregate,
                                           args=())
        self.aggregator.daemon = True  # thread dies with the program
        self.aggregator.start()
        pass

您可能不需要整个示例,但请随意剪切复制并粘贴您需要的内容。展示我如何进行线程处理也很重要。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

同时读取子进程的 stdout 和 stderr 的相关文章

随机推荐

  • 使用 `` 或 `@import` 包含 CSS - 哪个更好?

    我有一个网站 并且有多个用于打印 电视 屏幕 手持设备等的 css 样式表 我想知道这些方法中哪一种更好用 性能 可用 性等 or
  • 正则表达式问题组名称重新定义?

    所以我有这个正则表达式 s P
  • 线串长度(以英里为单位)

    我将运行数据表示为 Shapely LineStrings 其中 LineString 中的每个点都是一个坐标 我试图计算出以英里为单位的 LineString 长度 我知道 LineString 有一个length方法 但我不知道结果是什
  • 从 Spring Boot jar 文件运行非主类

    我有一个 spring boot jar 文件 里面有一个清单文件 如下所示 Manifest Version 1 0 Implementation Title myApp Implementation Version 0 1 Built
  • delphi中如何分割字符串

    我只需要分割一个字符串 例如 STANS Payment chk 1 1210 000进入一个基于数组 字符串列表中的结果将是 STANS Payment chk 1 1210 000 创建一个TStringList并将逗号分隔的字符串分配
  • 从订单示例构建订单簿[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找从订单构造订单簿的代码 例如 如果订单是 side price quantity buy 100 1 buy 101 10 buy
  • gcc中有128位整数吗?

    我想要一个 128 位整数 因为我想存储两个 64 位数字相乘的结果 gcc 4 4及以上版本有这样的东西吗 对于 C23 之前的 GCC 原始 128 位整数类型是仅在 64 位目标上可用 因此即使您已经检测到最新的 GCC 版本 您也需
  • 在事件处理程序中调用自定义挂钩

    我有一个名为的自定义钩子useFetchMyApi将 fetch 调用包装到 API 端点 函数钩子接受一个参数 并将其包含在帖子正文中 数据数组输出取决于钩子参数 在UI上 App组件调用useFetchMyApi一次 按钮单击处理程序将
  • 包含相同对象列表的对象的实体框架映射

    目前在我的代码中我正在做这样的事情 public class Subject private List
  • FLOPS 什么是真正的 FLOPS

    我来自这个线程 FLOPS Intel 核心并使用 C 语言对其进行测试 内积 https stackoverflow com questions 1536867 flops intel core and testing it with c
  • 将多个 div 与父级底部对齐

    我想将父级底部的 3 个 div 与100 height I tried parent height 100 display table cell vertical align bottom 但不起作用 即使您更改窗口的大小或分辨率 它也应
  • Android Studio Canary 2020.3.1:Kotlin 未解析的引用

    将 Android Studio Canary 版本更新到 3 1 后 我开始收到属于 kotlin 标准库的函数的 Kotlin 未解析引用 并且该问题似乎也影响了 Android Studio 导入正确库的能力 我相信我的问题类似于th
  • 为什么 null 不 in(1,2,3) false [重复]

    这个问题在这里已经有答案了 是否期望当我测试空值时not在列表中 结果始终为 false 那是 select Hello world where null not in 1 2 3 不要选择任何内容 因为 null not in 1 2 3
  • pycrypto 和 Google 应用引擎

    如何将 pycrypto 与 GAP 结合使用 It says here https developers google com appengine docs python tools libraries它不支持最新版本 这是否意味着我必须
  • 如何将值从子功能组件传递到父类组件?

    我有一个父类组件和一个子功能组件 我们如何将值从这种类型的子组件传递到父组件 我见过一些将值从子类组件传递到父类组件的示例 父组件 import React from react import ChildComponent from Chi
  • Heroku 上的 Resque 后台作业

    我在 Heroku 上遇到了一个非常奇怪的问题 我已经花了一段时间来解决这个问题 我的应用程序有一些外部 API 调用和邮件程序 我已将它们设置为在后台运行 ActiveJob 在 Heroku 上 我设置了两个工作人员 并且我正在使用 R
  • 如何在 Eclipse 中格式化 html 文件?

    XML 格式工作得很好 但 html 格式却不行 事实上 如果我对 html 文件使用 cmd shift F 它几乎会左对齐所有内容 我附上了之前和之后的照片 有谁知道如何解决这一问题 我尝试了 HTML 格式首选项 但没有成功 请注意
  • Maxima 中 Maple“unapply”或 Mathematica“Function”的模拟

    在 Wolfram Mathematica 中 我们可以定义作用于函数 即返回函数的函数 的运算符 例如至于下面示例中作用于两个参数的函数的第一个参数的乘法运算符 X f Function x y x f x y 然后我们可以将此运算符应用
  • 给定一个CGPath,如何让它弯曲?

    在下面的屏幕截图中 当您拖动单词气球的尾部 从气球连接到人的嘴的东西 时 形状会弯曲 如图中两个气球尾部之间的差异所示 我想知道 这是怎么做到的 我假设您需要从 CGPath 开始并对它做一些事情 有人知道这是什么吗 更新 所以如果我想弯曲
  • 同时读取子进程的 stdout 和 stderr

    我正在尝试在 Python 中运行一个冗长的命令 输出到 stdout 和 stderr 我想轮询子进程并将输出写入单独的文件 根据这个答案 我尝试了以下操作python 中 subprocess PIPE 的非阻塞读取 https sta