禁止从 Python 函数打印 stdout / stderr

2023-11-26

我有一个 Python 脚本,它使用我的雇主提供的一些封闭式 Python 函数(即我无法编辑这些函数)。当我调用这些函数时,它们会将输出打印到我想禁止的 Linux 终端。我尝试通过重定向 stdout / stderr;

orig_out = sys.stdout
sys.stdout = StringIO()
rogue_function()
sys.stdout = orig_out

但这无法捕获输出。我认为我通过 Python 调用的函数(上面的 rogue_function() )实际上是编译的 C 代码的包装器,它们实际上正在执行打印。

有谁知道我可以对函数(以及函数调用的任何子函数)传递给 stdout / stderr 的任何打印进行“深度捕获”?

UPDATE:

我最终采用了下面所选答案中概述的方法,并编写了一个上下文管理器来抑制 stdout 和 stderr:

# Define a context manager to suppress stdout and stderr.
class suppress_stdout_stderr(object):
    '''
    A context manager for doing a "deep suppression" of stdout and stderr in 
    Python, i.e. will suppress all print, even if the print originates in a 
    compiled C/Fortran sub-function.
       This will not suppress raised exceptions, since exceptions are printed
    to stderr just before a script exits, and after the context manager has
    exited (at least, I think that is why it lets exceptions through).      

    '''
    def __init__(self):
        # Open a pair of null files
        self.null_fds =  [os.open(os.devnull,os.O_RDWR) for x in range(2)]
        # Save the actual stdout (1) and stderr (2) file descriptors.
        self.save_fds = [os.dup(1), os.dup(2)]

    def __enter__(self):
        # Assign the null pointers to stdout and stderr.
        os.dup2(self.null_fds[0],1)
        os.dup2(self.null_fds[1],2)

    def __exit__(self, *_):
        # Re-assign the real stdout/stderr back to (1) and (2)
        os.dup2(self.save_fds[0],1)
        os.dup2(self.save_fds[1],2)
        # Close all file descriptors
        for fd in self.null_fds + self.save_fds:
            os.close(fd)

要使用它,您只需:

with suppress_stdout_stderr():
    rogue_function()

这工作“相当好”。它确实抑制了那些使我的脚本变得混乱的流氓函数的打印输出。我在测试它时注意到它允许引发异常以及一些记录器打印,但我不完全清楚为什么。我认为这与when这些消息被发送到 stdout / stderr (我认为它发生在我的上下文管理器退出之后)。如果有人能证实这一点,我有兴趣听到详细信息......


从 python 3.5 开始,我们可以使用内置函数以最少的工作来完成此操作contextlib,即redirect_stdout and redirect_stderr。我们只需要将这两个内置上下文管理器组合到我们的自定义上下文管理器中,这可以使用以下命令轻松完成Martijn 的回答中的好模式在这里。将两个输出重定向到os.devnull应该足够安全和​​便携。

from contextlib import contextmanager,redirect_stderr,redirect_stdout
from os import devnull

@contextmanager
def suppress_stdout_stderr():
    """A context manager that redirects stdout and stderr to devnull"""
    with open(devnull, 'w') as fnull:
        with redirect_stderr(fnull) as err, redirect_stdout(fnull) as out:
            yield (err, out)

注意抑制stderr当出现问题时仍然会给你完整的回溯,这是一件好事:

import sys

def rogue_function():
    print('spam to stdout')
    print('important warning', file=sys.stderr)
    1 + 'a'
    return 42

with suppress_stdout_stderr():
    rogue_function()

运行时仅打印上面的内容

Traceback (most recent call last):
  File "tmp.py", line 20, in <module>
    rogue_function()
  File "foo.py", line 16, in rogue_function
    1 + 'a'
TypeError: unsupported operand type(s) for +: 'int' and 'str'

到航站楼。未处理的异常永远不应该被忽视。

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

禁止从 Python 函数打印 stdout / stderr 的相关文章

随机推荐

  • Idea 中不显示字体

    更新 jrk7 openjdk 和 jre7 openjdk 字体后 Idea 中不显示字体 重新安装软件包 openjdk 和 idea 没有帮助 名称 a Linux ftp27host 3 14 6 1 ARCH 1 SMP PREE
  • 使用 pip 安装 uwsgi 时出现“ascii”编解码器无法解码错误

    我正在按照本教程设置 uwsgi https uwsgi readthedocs org en latest tutorials Django and nginx html I run pip install uwsgi在virtualen
  • Visual Studio - 用资源替换硬编码字符串的工具

    我有一个大型 ASP NET 项目 其中充满了硬编码字符串 现在必须将其提取到资源中 此类字符串几乎可以在任何地方找到 cs 文件 aspx 文件 ascx 文件等 并且文件数量巨大 我正在寻找一种工具 或任何方式 来一次找到所有这些硬编码
  • 从内存流读取存储的 PDF

    我正在使用 C 和 SQLServer 2012 开发一个数据库项目 在我的一个表单中 我有一个 PDF 文件 其中包含存储在表中的一些其他信息 这是成功的 但是当我想检索存储的信息时 我在显示 PDF 文件时遇到问题 因为我无法显示它 而
  • 具有多个数据库/DbContext 的 EF Code First 迁移

    我有两个数据库 每个数据库都有自己的 dbcontext 我设置了两个迁移配置 我可以为第一个数据库添加迁移 这很好 Add Migration DB1 InitialCreate ConfigurationTypeName DB1Conf
  • 使用 Jenkins Job-DSL 配置块将自定义步骤放置在特定位置

    我正在尝试使用 job dsl plugin 编写之前手动配置的大量 Jenkins 作业的配置脚本 这些作业的一种风格有多个步骤 其中包括使用 XShell 插件的几个步骤 job dsl 不直接支持这一点 不过 我应该能够通过使用自定义
  • 编写一个识别声音并执行操作的程序

    我想编写一个能够存储声音模式的程序 例如火车汽笛 喇叭 嘟嘟声 通过麦克风收听声音 然后在听到声音时采取一些行动 我懂一点Python 很早以前就用VB 编程过 我主要是一个 Oracle PLSQL 人员 该程序需要一个适度的用户界面 解
  • 消息通道是一个还是多个?

    我需要处理来自大约 30 个地址的电子邮件 我以一种将所有电子邮件发送到一个的方式来实现这一点DirectChannel之后到Receiver In Receiver我可以了解消息来自哪个地址 为此我创建了CustomMessageSour
  • jasperreport 5.0.1需要添加哪些依赖?

    I 升级jasper报告版本 from 4 5 0 至 5 1 0 当我安装插件时 它会抛出错误 例如缺少某些依赖项 我想使用 Maven 配置 JasperReports 5 1 0 Execution default of goal o
  • 安全 REST API,无需用户身份验证(无凭据)

    我已经为如何在没有用户身份验证的情况下保护 REST API 的安全而苦苦挣扎了 2 天 这是什么意思 在我的 AngularJS 应用程序中 我通过向我必须使用的现有服务 companydomain userinfo 发送 GET 请求来
  • Rails 路由 - 资源的自定义路由

    我目前正在构建一个 Rails 应用程序 我想坚持使用所有这些奇特的东西 例如 REST 和资源 但我想稍微自定义一下我的路线 我希望我的 GET 路线更加详细 我正在创建的应用程序是一个简单的博客 所以而不是GET posts 1我更喜欢
  • 在 CodeIgniter 中处理数据库错误的最佳实践

    我有一个带有唯一键的表 date userid 在我的网络应用程序数据库中 当我尝试插入现有记录时date and userid我收到以下错误 dupicate key in table 我在应用程序配置中打开了数据库调试器 因为我需要使用
  • 交错网格布局管理器动态列数

    我如何使动态列数RecyclerView using StaggeredGridLayoutManager 我已经有工作了RecyclerView 这是我需要做的屏幕 如果最大列是两个 那就很简单了 对于占据整个宽度的视图 setFullS
  • 将字符串的第一个字母大写,而不接触其他字母

    我想将字符串的第一个字母大写 但保留其余字母 我拥有的 赛车 我想要的是 赛车 然后只需将第一个字母大写str upper 并连接其余部分不变 string 0 upper string 1 Demo gt gt gt string rac
  • 测试 SQL 连接字符串可用性的最有效方法

    我有这段代码 我试图让它测试 SQL 字符串连接 但我不知道如何处理该部分connection Open true你能帮我解决这个问题吗 非常感谢您的参与 private void button1 Click object sender E
  • 使用 tcltk 在 R 脚本中添加弹出文本框

    我有一个很长的脚本来进行一些数据分析 它必须连接到多个数据库 其中一个数据库更新密码的频率往往比我想要的要高 因此我想添加一个弹出框供我输入当前密码 我找到了这个示例 但不了解足够的 tcltk 来查看当对话框关闭时 hwo 返回我的值 我
  • Rust 中的英文字母作为字符向量

    标题说明了一切 我想将字母表生成为字符向量 我确实考虑过简单地创建 97 122 的范围并将其转换为字符 但我希望有一种更好看的方式 例如 Python 的string ascii lower 生成的向量或字符串应包含字符 a z 对这类事
  • 如何使用knitr从r脚本函数生成多个文件

    我想从 r 脚本生成一些报告 我想避免从 rmd 文件编译时所需的重复 并且如果可能的话 我想从 r 脚本本身生成报告 该脚本具有一个函数 该函数应该从一系列数据帧生成每个报告 其中每个报告代表一个数据帧的处理 我只是不明白如何单独生成每个
  • JAVA中实例化的具体含义是什么

    我是一个JAVA新手 这次遇到了这个词叫做 在java中 在方法内部创建的类称为局部内部类 如果要调用局部内部类的方法 则必须实例化这个类在方法中 该词以粗体显示 谁能帮我解决这个问题 我知道这很尴尬 我应该进行更多研究 但我就是无法理解
  • 禁止从 Python 函数打印 stdout / stderr

    我有一个 Python 脚本 它使用我的雇主提供的一些封闭式 Python 函数 即我无法编辑这些函数 当我调用这些函数时 它们会将输出打印到我想禁止的 Linux 终端 我尝试通过重定向 stdout stderr orig out sy