Python 日志记录和子进程输出以及错误流

2024-03-28

我想启动一个 python 进程并将子进程错误消息记录到父脚本的日志记录对象中。理想情况下,我希望将日志流统一到一个文件中。我可以以某种方式访问​​日志记录类的输出流吗?我知道的一种解决方案是使用 proc log 进行日志记录。正如下面的答案中所述,我可以从 proc.stdin 和 stderr 中读取,但我有重复的日志记录头。我想知道是否有一种方法可以将日志记录类底层的文件描述符直接传递给子进程?

logging.basicConfig(filename="test.log",level=logging.DEBUG)
logging.info("Started")
procLog = open(os.path.expanduser("subproc.log"), 'w')
proc = subprocess.Popen(cmdStr, shell=True, stderr=procLog, stdout=procLog)
proc.wait()
procLog.flush()

基于亚当·罗森菲尔德的代码 https://stackoverflow.com/a/7730201/190597, 你可以

  1. use select.select阻塞直到有输出可供读取proc.stdout or proc.stderr,
  2. 读取并记录该输出,然后
  3. 重复直到该过程完成。

请注意,以下写入/tmp/test.log并运行命令ls -laR /tmp。更改以满足您的需求。

(PS:通常/tmp包含普通用户无法读取的目录,因此运行ls -laR /tmp向 stdout 和 stderr 生成输出。下面的代码在生成这两个流时正确地交错它们。)

import logging
import subprocess
import shlex
import select
import fcntl
import os
import errno
import contextlib

logger = logging.getLogger(__name__)

def make_async(fd):
    '''add the O_NONBLOCK flag to a file descriptor'''
    fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)

def read_async(fd):
    '''read some data from a file descriptor, ignoring EAGAIN errors'''
    try:
        return fd.read()
    except IOError, e:
        if e.errno != errno.EAGAIN:
            raise e
        else:
            return ''

def log_fds(fds):
    for fd in fds:
        out = read_async(fd)
        if out:
            logger.info(out)

@contextlib.contextmanager
def plain_logger():
    root = logging.getLogger()    
    hdlr = root.handlers[0]
    formatter_orig = hdlr.formatter
    hdlr.setFormatter(logging.Formatter('%(message)s'))
    yield 
    hdlr.setFormatter(formatter_orig)

def main():
    # fmt = '%(name)-12s: %(levelname)-8s %(message)s'
    logging.basicConfig(filename = '/tmp/test.log', mode = 'w',
                        level = logging.DEBUG)

    logger.info("Started")
    cmdStr = 'ls -laR /tmp'

    with plain_logger():
        proc = subprocess.Popen(shlex.split(cmdStr),
                                stdout = subprocess.PIPE, stderr = subprocess.PIPE)
        # without `make_async`, `fd.read` in `read_async` blocks.
        make_async(proc.stdout)
        make_async(proc.stderr)
        while True:
            # Wait for data to become available 
            rlist, wlist, xlist = select.select([proc.stdout, proc.stderr], [], [])
            log_fds(rlist)
            if proc.poll() is not None:
                # Corner case: check if more output was created
                # between the last call to read_async and now                
                log_fds([proc.stdout, proc.stderr])                
                break

    logger.info("Done")

if __name__ == '__main__':
    main()

Edit:

您可以重定向stdout and stderr to logfile = open('/tmp/test.log', 'a')。 然而,这样做的一个小困难是,任何同时写入的记录器处理程序/tmp/test.log将不知道子进程正在写入什么,因此日志文件可能会出现乱码。

如果在子进程执行其业务时不进行日志记录调用,则唯一的问题是记录器处理程序在子进程完成后在文件中的位置错误。这可以通过调用来修复

handler.stream.seek(0, 2)

因此处理程序将在文件末尾恢复写入。


import logging
import subprocess
import contextlib
import shlex

logger = logging.getLogger(__name__)

@contextlib.contextmanager
def suspended_logger():
    root = logging.getLogger()    
    handler = root.handlers[0]
    yield 
    handler.stream.seek(0, 2)

def main():
    logging.basicConfig(filename = '/tmp/test.log', filemode = 'w',
                        level = logging.DEBUG)

    logger.info("Started")
    with suspended_logger():
        cmdStr = 'test2.py 1>>/tmp/test.log 2>&1'
        logfile = open('/tmp/test.log', 'a')
        proc = subprocess.Popen(shlex.split(cmdStr),
                                stdout = logfile,
                                stderr = logfile)
        proc.communicate()
    logger.info("Done")

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

Python 日志记录和子进程输出以及错误流 的相关文章

  • 在 Python 中使用 argparse 处理无效参数

    我在用argparse https docs python org 2 library argparse html解析命令行参数 默认情况下 在收到无效参数时 它会打印帮助消息并退出 是否可以自定义 argparse 在收到无效参数时的行为
  • 时间序列的线性回归Python(numpy或pandas)

    我对 python 和一般编程都很陌生 所以请原谅任何简单的错误 应该显而易见的事情 我想做的事情非常简单 我只想将线性趋势 一维多项式 拟合到一堆时间序列上 看看斜率是正还是负 现在我只是想让它在一个时间序列中工作 问题 pandas 和
  • Beautiful Soup 中 find_all 方法的返回类型是什么?

    from bs4 import BeautifulSoup SoupStrainer from urllib request import urlopen import pandas as pd import numpy as np imp
  • 如何在 jupyter 笔记本中导入 scikit-learn?

    我创建了一个新的 conda 环境来使用 scikit learn 并使用conda install
  • Pandas:删除具有纳米值索引的行

    给定以下 pandas DataFrame 其中一些索引是NaN 如何删除第三行和第八行 因为它们的索引是NaN Thanks import pandas as pd import numpy as np data list abcdefg
  • 用于多输入图像的 VGG16 网络

    我正在尝试将 VGG16 网络用于多个输入图像 使用具有 2 个输入的简单 CNN 训练该模型给了我一个 acc 大约 50 这就是为什么我想使用 VGG16 这样的既定模型进行尝试 这是我尝试过的 imports from keras a
  • 自定义 pytest junitxml 失败报告

    我正在尝试内省测试失败并将附加数据包含到 junit xml 测试报告中 具体来说 这是对外部产品的一套功能测试 我想将产品的日志包含到故障报告中 使用找到的方法here https stackoverflow com questions
  • Python/pandas:从两个数据帧中查找匹配值并返回第三个值

    我有两个不同的数据帧 df1 df2 具有完全不同的形状 df1 64 6 df2 564 9 df1 包含一列 df1 objectdesc 其中的值 字符串 也可以在 df2 df2 objdescription 的列中找到 由于两个数
  • 如何获取类变量和类型提示?

    假设我定义一个类 其中包含带有类型提示的类级别变量 例如新的 python 3 7dataclasses class Person name str age int def parse me self what do I do here 我
  • 具有透明框架和不透明边缘的图例

    设置图例透明度时 plt legend framealpha 0 5 它会影响背景和边缘 如何仅将透明度应用于背景而不应用于边缘 我努力了 plt legend edgecolor 0 0 0 1 facecolor 1 1 1 0 1 我
  • 单词和表情符号计数器

    我有一个包含 clear message 列的数据框 并且创建了一个用于计算每行中所有单词的列 history word count history clear message apply lambda x Counter x split
  • buildozer android NDK 未下载 Ubuntu

    我使用的是 Ubuntu 16 04 LTS 操作系统 我已经在 python2 和 python3 中安装了 buildozer android sdk 已安装 但 buildozer 在下载 android NDK 时显示错误 请帮我解
  • 如何设置 QTableView 中特定单元格的线条样式?

    我正在使用 QT GUI 我正在使用 QTableView 实现一个简单的十六进制编辑控件 我最初的想法是使用一个有十七列的表格 表的每一行都有 16 个十六进制字节 然后在第十七列中显示该数据的 ASCII 表示形式 理想情况下 我想编辑
  • Python 中函数未定义错误

    我试图在 python 中定义一个基本函数 但当我运行一个简单的测试程序时 我总是收到以下错误 gt gt gt pyth test 1 2 Traceback most recent call last File
  • 如何复制 tf.keras.models.Model 子类?

    我需要复制 keras 模型 但我无法知道可以做什么 除非该模型is not a tf keras models Model 子类 Note 使用copy deepcopy 将在没有任何错误的情况下工作 但是每当使用副本时都会导致另一个错误
  • 后视模式无效

    为什么这个正则表达式在 Python 中有效 但在 Ruby 中无效
  • 将收藏计数器变成字典

    我有一个由该函数产生的集合结果 Counter df email address 它返回每个单独的电子邮件地址及其重复次数 Counter nan 1618 email protected cdn cgi l email protectio
  • 在可序列化 Java 类中使用记录器的正确方法是什么?

    我有以下 doctored 我正在开发的系统中的类以及Findbugs http findbugs sourceforge net 正在生成一个SE BAD FIELD http findbugs sourceforge net bugDe
  • 带有第二个 y 轴的 Seaborn 图

    i wanted to know how to make a plot with two y axis so that my plot that looks like this to something more like this by
  • 将多列传递给 groupby.transform

    据我所知 当您使用 DataFrame 列调用 groupby transform 时 该列将传递给转换数据的函数 但我无法理解的是如何将多个列传递给函数 people DataFrame np random randn 5 5 colum

随机推荐

  • 我可以在没有自己的后端服务器的情况下在 React 中实现 Stripe checkout 吗?

    我在 Netlify 上部署了一个 React 前端 我想实现一个简单的支付系统 用户可以输入他们想要的金额并使用 Stripe 结帐甚至 PayPal 进行支付 我想知道这是否可以在不支付单独后端费用的情况下实现 或者您可以建议其他任何自
  • 如何使用 jquery 追加整个 html 文件

    我有一个像这样的html文件 some content some content 我的问题是如何使用 jquery 加载这个文件作为一个整体 我尝试过 我搜索了很长一段时间的解决方案 但只找到了很多方法来附加html文件的某些部分 例如元
  • Android 通用 AsyncTask 类

    我看过这个答案 由于 AsyncTask 是一个单独的类 如何将 OnPostExecute 的结果获取到主活动 https stackoverflow com questions 12575068 how to get the resul
  • AngularJS ng-repeat 通过复杂和动态的 JSON 数组

    我正在尝试使用 JSON 数组向用户显示内容ng repeat选项 这JSON Array是动态创建的 所以我有点困惑如何向用户显示相同的内容 的语法JSON ARRAY内容如下COMPLEX key可以动态增加或减少 jsonList n
  • ASP.Net core-从中间件获取routetemplate值

    我有一个中间件 每次对我的 API 发出请求时都会调用该中间件 我想记录路由模板以及来自该中间件的请求的持续时间 如何在我的中间件代码中获取路由模板 路由模板类似于 products productId 这是我如何让它发挥作用的 我在过滤器
  • 如何使用 Python 和 Django 创建 SaaS 应用程序

    您能给我一些建议 让您可以使用 Python 和 Django 创建 SaaS 软件即服务 应用程序吗 目前我不明白的一般主题是 您是否为所有客户提供一个可用的应用程序 或者为每个客户提供一个应用程序 如何管理每个客户端的数据库访问 权限或
  • 原生原型与 $.extension()

    在工作中 我们使用 jQuery 在我们开始使用它后不久 我看到几个开发人员正在向文件 jquery extensions js 添加函数 在里面 我发现添加了一大堆方法 这本质上相当于 jQuery 上的静态方法 这里有一些 format
  • Apache 目录 LDAP - 分页搜索

    我一直在寻找使用 Apache Directory API 执行分页搜索的信息 但我没有找到任何示例或任何有关如何使用正确的 PagedResults 控件构建 SearchRequest 然后执行搜索的信息 你们有什么建议吗 或者知道哪里
  • TextToSpeech 改变声音

    我希望能够更改文本转语音 API 中的语音 例如更改 声音由女声转为男声 让声音更清晰 改变语速 请有人让我知道这是否可能 谢谢 您可以通过以下方式为特定字符串提供自己的转换addSpeech 不过 AFAICT 没有文档说明如何替换自己的
  • 如何构建这个项目? (jpeg 库)

    Edit 我现在正在使用http code google com p jpeg compressor http code google com p jpeg compressor 所以我不再关心让这个工作了 我下载了http ijg org
  • 从日语 IME 获取更多数据

    在我的 C 表单中 我有一个数据网格视图 我想在其中输入单词或句子的汉字和假名版本 并将它们放在不同的列中 例如 転寝 寝坊 我想要实现的是当我提交第一列时自动填充第二列 我知道有一些词典包含汉字读法 但对于句子来说它会变得复杂 而且还有很
  • 使用 VisualVM 和 JMX 进行远程监控

    我想使用 jvisualvm 或 jconsole 监视远程运行的 java spring boot 应用程序 在本地运行时 我可以在 jvisualvm 和 jconsole 中看到托管 bean 远程运行时我无法连接 我用几个不同的ja
  • 得到一个名为保留字的Oracle表,可能会出现哪些问题?

    我们刚刚外包了一个系统 乍一看我可以看到一些名称为 CASE 或 FROM 的表和字段 它是一个 Oracle 10g DB 我们将使用来自 Java Hibernate C C 的这些数据 有什么特别我们应该注意的吗 对于我在其他帖子中看
  • jQuery:一年中的一周脚本正在运行

    不久前我需要一个脚本来每周更新一些内容 我的问题在这个论坛 https stackoverflow com questions 3701276 jquery update content every week or long period
  • CMS 软件中的空白 index.html 而不是 .htaccess

    我注意到 Joomla Wordpress 和其他 CMS 在其所有子文件夹中都有空白的 index html 文件 以防止人们窥视文件夹结构 我的问题是为什么他们不能禁止使用 htaccess 文件查看文件夹 而不是将空白的 index
  • 多个 goroutine 的 Go 内存消耗

    我试图检查 Go 在 100 000 个 goroutine 上的表现如何 我编写了一个简单的程序来生成许多例程 除了打印一些公告之外什么也不做 我将 MaxStack 大小限制为仅 512 字节 但我注意到程序大小并没有随之减小 它消耗了
  • 从运行脚本阶段获取当前方案名称

    有没有办法从运行脚本阶段获取当前方案 我试过了 SCHEME NAME 但它不存在 我找不到要使用的环境变量 因此我必须开发一种解决方法 将方案名称写入磁盘建立预行动然后将其读回运行脚本 phase 对于您感兴趣的每个方案 请访问编辑方案并
  • LibGDX:如何使平铺地图图块可点击?

    如何为平铺地图中的图块添加点击侦听器 以便当您用鼠标选择图块时它会突出显示 libGDX 不直接支持这一点 因为 TiledMap 内容仅用于渲染 您可以轻松创建一个Stage不过 它将充当 TiledMap 的某种覆盖输入层 只需创建一个
  • 线程中的 GLib GMainContext?

    我在堆栈溢出上搜索以找到与我的问题相关的答案 但我没有找到任何答案 我有一个启动线程的主线程 我的 main 函数 新线程运行 GMainLoop 在我的主要功能中 我不断通过调用添加源g io watch一些文件描述符 但如果事件被调度
  • Python 日志记录和子进程输出以及错误流

    我想启动一个 python 进程并将子进程错误消息记录到父脚本的日志记录对象中 理想情况下 我希望将日志流统一到一个文件中 我可以以某种方式访问 日志记录类的输出流吗 我知道的一种解决方案是使用 proc log 进行日志记录 正如下面的答