将 sys.stdout 重定向到 python 日志记录

2024-04-26

所以现在我们有很多 python 脚本,我们正在尝试整合它们并修复和冗余。我们正在尝试做的事情之一是确保所有 sys.stdout/sys.stderr 都进入 python 日志记录模块。

现在最重要的是,我们希望打印出以下内容:

[<ERROR LEVEL>] | <TIME> | <WHERE> | <MSG>

现在所有Python错误消息中的sys.stdout / sys.stderr消息几乎都是[LEVEL] - MSG的格式,它们都是使用sys.stdout/sys.stderr编写的。我可以在 sys.stdout 包装器和 sys.stderr 包装器中解析罚款。然后根据解析的输入调用相应的日志记录级别。

所以基本上我们有一个名为 foo 的包和一个名为 log 的子包。在__init__.py我们定义如下:

def initLogging(default_level = logging.INFO, stdout_wrapper = None, \
                stderr_wrapper = None):
    """
        Initialize the default logging sub system
    """
    root_logger = logging.getLogger('')
    strm_out = logging.StreamHandler(sys.__stdout__)
    strm_out.setFormatter(logging.Formatter(DEFAULT_LOG_TIME_FORMAT, \
                                            DEFAULT_LOG_TIME_FORMAT))
    root_logger.setLevel(default_level)
    root_logger.addHandler(strm_out)

    console_logger = logging.getLogger(LOGGER_CONSOLE)
    strm_out = logging.StreamHandler(sys.__stdout__)
    #strm_out.setFormatter(logging.Formatter(DEFAULT_LOG_MSG_FORMAT, \
    #                                        DEFAULT_LOG_TIME_FORMAT))
    console_logger.setLevel(logging.INFO)
    console_logger.addHandler(strm_out)

    if stdout_wrapper:
        sys.stdout = stdout_wrapper
    if stderr_wrapper:
        sys.stderr = stderr_wrapper


def cleanMsg(msg, is_stderr = False):
    logy = logging.getLogger('MSG')
    msg = msg.rstrip('\n').lstrip('\n')
    p_level = r'^(\s+)?\[(?P<LEVEL>\w+)\](\s+)?(?P<MSG>.*)$'
    m = re.match(p_level, msg)
    if m:
        msg = m.group('MSG')
        if m.group('LEVEL') in ('WARNING'):
            logy.warning(msg)
            return
        elif m.group('LEVEL') in ('ERROR'):
            logy.error(msg)
            return
    if is_stderr:
        logy.error(msg)
    else:
        logy.info(msg)

class StdOutWrapper:
    """
        Call wrapper for stdout
    """
    def write(self, s):
        cleanMsg(s, False)

class StdErrWrapper:
    """
        Call wrapper for stderr
    """
    def write(self, s):
        cleanMsg(s, True)

现在我们将在我们的一个脚本中调用它,例如:

import foo.log
foo.log.initLogging(20, foo.log.StdOutWrapper(), foo.log.StdErrWrapper())
sys.stdout.write('[ERROR] Foobar blew')

这将被转换为错误日志消息。喜欢:

[ERROR] | 20090610 083215 | __init__.py | Foobar Blew

现在的问题是,当我们这样做时,记录错误消息的模块现在是__init__(对应于foo.log.__init__.py文件)这违背了整个目的。

我尝试对 stderr/stdout 对象进行深层复制/浅层复制,但这没有任何作用,它仍然显示消息发生的模块__init__.py。我怎样才能做到这一点,这样就不会发生这种情况?


问题是日志记录模块正在调用堆栈上查找单层以查找调用它的人,但现在您的函数此时是中间层(尽管我希望它报告cleanMsg, not __init__,因为这就是您调用 log() 的地方)。相反,您需要它上升两个级别,或者将呼叫者的身份传递到记录的消息中。您可以通过自己检查堆栈帧并获取调用函数并将其插入消息中来完成此操作。

要找到您的调用框架,您可以使用检查模块:

import inspect
f = inspect.currentframe(N)

将查找 N 帧,并返回帧指针。即您的直接调用者是 currentframe(1),但如果这是 stdout.write 方法,您可能必须转到另一个帧。 一旦获得调用框架,您就可以获得执行代码对象,并查看与其关联的文件和函数名称。例如:

code = f.f_code
caller = '%s:%s' % (code.co_filename, code.co_name)

您可能还需要添加一些代码来处理非 python 代码调用(即 C 函数或内置函数),因为它们可能缺少 f_code 对象。

或者,跟进迈克的回答 https://stackoverflow.com/questions/975248/redirecting-sys-stdout-to-python-logging/975504#975504,您可以在继承自logging.Logger的自定义Logger类中使用相同的方法,该类重写findCaller以向上导航几个帧,而不是一个帧。

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

将 sys.stdout 重定向到 python 日志记录 的相关文章

  • Android studio 在日志猫中“清除全部”,更改日志级别过滤器时日志仍然会回来

    在 LogCat 中 当我单击 全部清除 按钮时 它似乎清除了所有日志 但是 如果我更改日志级别并返回到之前的日志级别 则所有日志都会返回 例如 我正在查看 Verbose 我选择 全部清除 日志清除 我切换到 调试 我切换回 详细 现在所
  • 没有任何元数据的 zip 文件

    我想找到一种简单的方法来压缩一堆文件 而无需任何文件元数据 例如时间戳 这zip命令似乎总是保留元数据 我没有找到禁用元数据的方法 我希望解决方案是一个命令或最多一个 python 脚本 谢谢 正如一些帖子已经指出的那样 zip 标头中的大
  • 在 Pandas 中按日期获取有效合约

    我在检测 pandas DataFrame 中的活动合约方面遇到了一些困难 假设每一行都是一个协商 对于每一行 我有两列 initial date 和 end date 我想知道的是按日期划分的活跃合约数量 到目前为止我做了一个非常低效的方
  • 从正在运行的 python 脚本检测优化标志是否为 -O 或 -OO

    有时我想生成一个子进程 其优化标志与启动父进程时使用的优 化标志相同 我可以使用类似的东西 optimize not debug 但这样我就可以匹配两者 O and OO flags 是否有一些 python 内部状态包含该信息 经过一番深
  • 在python中将文本文件解析为列表

    我对 Python 完全陌生 我正在尝试读取包含单词和数字组合的 txt 文件 我可以很好地读取 txt 文件 但我正在努力将字符串转换为我可以使用的格式 import matplotlib pyplot as plt import num
  • Pandas重置索引未生效[重复]

    这个问题在这里已经有答案了 我不确定我在哪里误入歧途 但我似乎无法重置数据帧上的索引 当我跑步时test head 我得到以下输出 正如您所看到的 数据帧是一个切片 因此索引超出范围 我想做的是重置该数据帧的索引 所以我跑test rese
  • 为什么 Python 中的“pip install”会引发语法错误?

    我正在尝试使用 pip 安装软件包 我试着跑pip install从Python shell 但我得到了SyntaxError 为什么我会收到此错误 如何使用 pip 安装软件包 gt gt gt pip install selenium
  • 创建一个类似于 Tkinter 的表

    我希望创建类似于 Tkinter 中的表格的东西 但它不一定是这样的 例如 我想创建标题 Name1 Name2 Value 并在每个标题下面有几个空白行 然后 我希望稍后用我计算的值或名称的字符串值填充这些行 因此是标签 对于 Name2
  • 如何在 Python 中将彩色输出打印到终端?

    是否有与 Perl 等效的 Python 语言 print color red print
  • 如何使用Python的super()来更新父值?

    我对继承很陌生 之前所有关于继承和 Python 的 super 函数的讨论都有点超出我的理解 我当前使用以下代码来更新父对象的值 usr bin env python test py class Master object mydata
  • PHP 日志文件颜色

    我正在编写一个 PHP 日志文件类 但我想为写入文件的行添加颜色 我遇到的问题是颜色也会改变终端的颜色 我想要实现的是仅更改写入日志文件的行的颜色 class logClass extends Singleton private funct
  • 为什么我用 beautifulSoup 刮的时候有桌子,但没有 pandas

    尝试抓取条目页面转换为制表符分隔格式 主要拉出序列和 UniProt 登录号 当我跑步时 url www signalpeptide de index php sess m listspdb bacteria s details id 10
  • 将输入发送到 python 子进程而不等待结果

    我正在尝试为一段代码编写一些基本测试 该代码通常通过 stdin 无休止地接受输入 直到给出特定的退出命令 我想检查程序是否在给出一些输入字符串时崩溃 经过一段时间来考虑处理 但似乎无法弄清楚如何发送数据而不是陷入等待我不知道的输出关心 我
  • 无法截取宽度为 0 的屏幕截图

    我正在尝试截取 Bootstrap 模态内元素的屏幕截图 经过一番努力 我终于想出了这段代码 driver get https enlinea sunedu gob pe driver find element by xpath div c
  • 查找给定节点的最高权重边

    我在 NetworkX 中有一个有向图 边缘的权重从 0 到 1 表示它们发生的概率 网络连通性非常高 所以我想修剪每个节点的边缘 只保留最高概率的节点 我不确定如何迭代每个节点并仅保留最高权重in edges在图中 有没有一个networ
  • 为什么实现 __iter__ 的对象不被识别为可迭代的?

    假设您使用包装对象 class IterOrNotIter def init self self f open tmp toto txt def getattr self item try return self getattribute
  • Python组合目录中的所有csv文件并按日期时间排序

    我有 2 年的每日数据分成每月文件 我想将所有这些数据合并到一个按日期和时间排序的文件中 我正在使用的代码组合了所有文件 但不按顺序 我正在使用的代码 import pandas as pd import glob os import cs
  • 全局变量是 None 而不是实例 - Python

    我正在处理Python 中的全局变量 代码应该可以正常工作 但是有一个问题 我必须使用全局变量作为类的实例Back 当我运行应用程序时 它说 back is None 这应该不是真的 因为第二行setup 功能 back Back Back
  • 异步和协程与任务队列

    我一直在阅读有关 python 3 中的 asyncio 模块的内容 以及更广泛地了解 python 中的协程的内容 但我不明白是什么让 asyncio 成为如此出色的工具 我的感觉是 你可以用协程做的所有事情 通过使用基于多处理模块 例如
  • Django South - 将 null=True 字段转换为 null=False 字段

    我的问题是 转变的最佳做法是什么null True场变成null False使用 Django South 的字段 具体来说 我正在与ForeignKey 你应该先写一个数据迁移 http south aeracode org docs t

随机推荐

  • 类型“Request”上不存在属性“”

    当试图延长Request包中的接口express要添加一些自定义属性 我收到以下打字稿错误 TS2339 Property does not exist on type Request
  • 如何在pyplot中自动标注最大值

    我试图弄清楚如何自动注释图形窗口中的最大值 我知道您可以通过手动输入 x y 坐标来注释您想要使用的任何点来完成此操作 annotate 方法 但我希望注释是自动的 或者自己找到最大值点 到目前为止 这是我的代码 import matplo
  • JMX 的使用以及如何用于现有应用程序

    几年前我们就在 JDK 5 上开发了分布式 Web 应用程序 JMX 将如何帮助这个应用程序 1 它能帮助我监控性能 内存 CPU 以及网络和磁盘 IO 吗 2 如果是这样 那么应用程序部署在多个服务器中 我如何在一个仪表板中进行监控 3
  • 为什么所有的 Active Record 都讨厌? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 Ruby 中将…(省略号)更改为…(三个句点)?

    我正在解析这个文件 http msdn microsoft com en us library ms189782 aspx using nokogiri 我发现有一些 省略号 该页面中的字符且无法删除 我想知道如何用Ruby来替换所有 省略
  • JavaScript 正则表达式异常(无效组)

    我有以下正则表达式 lt index d g 我正在尝试在像这样的字符串中查找索引整数 some text index 1 id 2 value 3 该表达式在 php 中工作正常 但在 javascript 中不起作用 我收到以下错误 未
  • 以正常形式打印浮点数,而不是指数形式/科学记数法[重复]

    这个问题在这里已经有答案了 我有一个以指数形式打印的数字 gt gt gt gt gt gt a 1 1221759 gt gt gt print a 8 184920266599223e 07 gt gt gt 我怎样才能让它以正常形式打
  • 如何在express和node中从html表单发送put请求

    我有一个用于编辑对象的表单 我想使用 Express 3 x 和 node js 正确处理它 编辑物品路线 item edit显示用于编辑对象的表单 我想我有三个选择 1 放置一个值为 edit 的隐藏字段 这样我就可以在express中正
  • 使用 MVCMailer 尝试发送到非本地电子邮件地址时,邮件服务器需要身份验证

    我想向用户发送新闻通讯电子邮件 我已经这样做了 public ActionResult SendNewsLetter userMailer NewsLetter Send return View 在 userMailer 类中 public
  • 基于超简单静态文件(html)的php站点缓存

    我有一个网站 基本上只显示内容 没有任何表格和后期处理 该网站基于 PHP 并托管在共享主机上 它很少改变 我想为此网站启用缓存 它是共享托管 所以我需要一个解决方案 不使用 Memcached 不需要将我的网站移至 VPS 不要使用APC
  • 如何删除firestore自动生成的单字段索引?

    update 太长了 如果您到达这里 您应该重新检查构建数据库的方式 随着时间的推移 您的文档可能会被消耗 由于嵌套列表等 原问题 我有一个包含很多字段的文档集合 我不查询文档 甚至不查询简单的查询 我只使用 db collection m
  • Spark Streaming 中的 ML 模型更新

    我通过 Spark 批处理作业在 HDFS 中保留了机器学习模型 并且我在 Spark 流中使用它 基本上 ML 模型从 Spark Driver 广播到所有执行器 有人可以建议我如何在不停止 Spark Streaming 作业的情况下实
  • 如何将 jQuery UI 日期选择器初始化为查询字符串中的日期?

    鉴于此标记 Calendar html date 1 2 2003 div class inlinedatepicker div 这将毫不费力地显示一个内联日期选择器 太棒了 如何将日期选择器预设为通过查询字符串传入的日期 请注意 在本例中
  • Materialise CSS 侧面导航不起作用

    我已经对 Materialise 运行进行了基本设置 除了滑出侧面导航之外 一切似乎都很好 这是我的代码 菜单 ul class right hide on med and down li a class dropdown button h
  • 是否可以将 ComboBox DisplayMember 设置为列表中对象的属性?

    我有一个正在填充的 ComboBox 其中 ComboBox Items 中的每个对象都是对象列表 目前 组合框为每个项目显示 集合 是否可以让组合框显示列表中包含组合框项目的第一个对象的成员 我目前正在通过以下内容填充组合框项目 fore
  • vue组件设置child的数据值

    我正在使用 vue 轮播 https ssense github io vue carousel api https ssense github io vue carousel api 它运行良好 但我需要重置轮播 我可以看到当前页面有一个
  • 如何在node.js EJS视图中转义HTML?

    我想转义 bloglist i Text 字段中的 html 如何使用 EJS 做到这一点 h1 h1 p Welcome to p h3 h3 div div
  • R:从数据表中选择范围内的值

    我在 R 中有一个数据表 name date John 1156649280 Adam 1255701960 etc 我想获取日期在某个范围内的所有行 在 SQL 中 我可能会说SELECT FROM mytable WHERE date
  • Scala 映射 foreach

    given val m Map String Int a gt 1 b gt 2 c gt 3 m foreach key String value Int gt println gt gt gt key key value value 为
  • 将 sys.stdout 重定向到 python 日志记录

    所以现在我们有很多 python 脚本 我们正在尝试整合它们并修复和冗余 我们正在尝试做的事情之一是确保所有 sys stdout sys stderr 都进入 python 日志记录模块 现在最重要的是 我们希望打印出以下内容