如何以一般方式使 Python 函数运行的可执行文件的终端输出静音?

2023-12-24

我想抑制运行可执行文件的函数产生的所有终端输出。

我尝试使用上下文管理器来抑制 Python 函数的输出,该上下文管理器在每次调用函数时临时重新定义 stdout 和 stderr。这抑制了由产生的终端输出print在函数中调用,但当函数调用产生终端输出的可执行文件时,它似乎不起作用。

那么,如何抑制 Python 函数调用的可执行文件的输出呢?

我的代码如下。我已经包含了一个调用的示例函数ls尝试说明我想要抑制的终端输出类型(尽管我正在处理的函数不同)。

#!/usr/bin/env python

import os
import subprocess
import sys

def main():

    print("hello")

    with silence():
        print("there")

    print("world")

    with silence():
        engage_command(command = "ls")

class silence(object):

    def __init__(
        self,
        stdout = None,
        stderr = None
        ):
        if stdout == None and stderr == None:
            devnull = open(os.devnull, "w")
            stdout = devnull
            stderr = devnull
        self._stdout = stdout or sys.stdout
        self._stderr = stderr or sys.stderr

    def __enter__(
        self
        ):
        self.old_stdout = sys.stdout
        self.old_stderr = sys.stderr
        self.old_stdout.flush()
        self.old_stderr.flush()
        sys.stdout = self._stdout
        sys.stderr = self._stderr

    def __exit__(
        self,
        exc_type,
        exc_value,
        traceback
        ):
        self._stdout.flush()
        self._stderr.flush()
        sys.stdout = self.old_stdout
        sys.stderr = self.old_stderr

def engage_command(
    command = None
    ):
    process = subprocess.Popen(
        [command],
        shell      = True,
        executable = "/bin/bash")
    process.wait()
    output, errors = process.communicate()
    return output

if __name__ == "__main__":
    main()

在我的特定情况下,我尝试运行以下函数(而不是ls上面的函数):

with propyte.silence():
    stream = pyaudio.PyAudio().open(
        format   = pyaudio.PyAudio().get_format_from_width(1),
        channels = 1, 
        rate     = bitrate, 
        output   = True
    )

运行时,会产生如下输出:

ALSA lib pcm_dsnoop.c:606:(snd_pcm_dsnoop_open) unable to open slave
ALSA lib pcm_dmix.c:1029:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_dmix.c:1029:(snd_pcm_dmix_open) unable to open slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock

我想抑制该输出。


编辑:测试一个办法 https://stackoverflow.com/a/36966379/1556092由@Matthias 提供

#!/usr/bin/env python

import contextlib
import os
import subprocess
import sys

def main():

    print("hello")

    with silence():
        print("there")

    print("world")

    with silence():
        engage_command(command = "ls")

@contextlib.contextmanager
def silence():
    devnull = os.open(os.devnull, os.O_WRONLY)
    old_stderr = os.dup(2)
    sys.stderr.flush()
    os.dup2(devnull, 2)
    os.close(devnull)
    try:
        yield
    finally:
        os.dup2(old_stderr, 2)
        os.close(old_stderr)

def engage_command(
    command = None
    ):
    process = subprocess.Popen(
        [command],
        shell      = True,
        executable = "/bin/bash")
    process.wait()
    output, errors = process.communicate()
    return output

if __name__ == "__main__":
    main()

我没有成功地抑制终端输出print or the ls我不知道为什么。


您可以从 PyAudio 切换到声音装置 http://python-sounddevice.readthedocs.io/模块,它已经负责使终端输出静音(请参阅#12 https://github.com/spatialaudio/python-sounddevice/pull/12)。这是如何完成的(使用 CFFI):

from cffi import FFI
import os

ffi = FFI()
ffi.cdef("""
/* from stdio.h */
FILE* fopen(const char* path, const char* mode);
int fclose(FILE* fp);
FILE* stderr;  /* GNU C library */
FILE* __stderrp;  /* Mac OS X */
""")
try:
    stdio = ffi.dlopen(None)
    devnull = stdio.fopen(os.devnull.encode(), b'w')
except OSError:
    return
try:
    stdio.stderr = devnull
except KeyError:
    try:
        stdio.__stderrp = devnull
    except KeyError:
        stdio.fclose(devnull)

如果你想要一个纯Python的解决方案,你可以尝试这个上下文管理器:

import contextlib
import os
import sys

@contextlib.contextmanager
def ignore_stderr():
    devnull = os.open(os.devnull, os.O_WRONLY)
    old_stderr = os.dup(2)
    sys.stderr.flush()
    os.dup2(devnull, 2)
    os.close(devnull)
    try:
        yield
    finally:
        os.dup2(old_stderr, 2)
        os.close(old_stderr)

这是一篇关于该主题的非常有用的博客文章:http://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/ http://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/.


UPDATE:

上面的上下文管理器静默标准错误输出(stderr),用于原始问题中提到的来自 PortAudio 的烦人消息。摆脱标准输出(stdout),正如在您更新的问题中一样,您必须替换sys.stderr with sys.stdout和文件描述符2与号码1:

@contextlib.contextmanager
def ignore_stdout():
    devnull = os.open(os.devnull, os.O_WRONLY)
    old_stdout = os.dup(1)
    sys.stdout.flush()
    os.dup2(devnull, 1)
    os.close(devnull)
    try:
        yield
    finally:
        os.dup2(old_stdout, 1)
        os.close(old_stdout)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何以一般方式使 Python 函数运行的可执行文件的终端输出静音? 的相关文章

随机推荐

  • 如何在 Midnight Commander 中过滤目录

    也许是一个愚蠢的问题 但如何在 Midnight Commander 中过滤目录 例如 我有一个包含很多目录的文件夹 其命名如下 holidays 2016 birthdays 2016 holidays 2015 我怎样才能过滤像 201
  • 绘制平滑曲线 - 所需方法

    如何在移动时平滑 iOS 绘图应用程序中的一组点 我尝试过 UIBezierpaths 但当我只是将点 1 2 3 4 2 3 4 5 移动时 我得到的只是它们相交处的锯齿状末端 我听说过样条曲线和所有其他类型 我对 iPhone 编程很陌
  • ConfigurationManager.GetSection(sectionName) 在执行单元测试时返回 null

    我有一个自己的单元测试项目app config文件 它是由正在测试的目标项目定义的真实配置文件的模拟 该模拟文件由单元测试代码 而不是目标项目 加载和处理 如果我仅在这一个测试项目中运行测试 则它可以正常工作 ConfigurationMa
  • WCF:更新服务参考提供重复的配置条目

    我有一个使用 WCF 服务的服务引用的 WPF 应用程序 在对服务进行更新时 我需要更新服务引用 因此我右键单击它并点击 更新服务引用 执行此操作会导致客户端项目的 App config 文件中出现重复条目 它复制了下面的绑定wsHttpB
  • 在SVN Trunk中完全禁用Django的CSRF保护

    我沮丧地花了几个小时 试图禁用 Django 现在试图强加给我的 CSRF 但没有成功 还有其他人尝试过更成功吗 我对任何有效的东西都很好 除了源补丁 但猴子补丁还可以 不要这样做 但如果你必须的话 try this http johnmc
  • NativeActivity 活动的父活动类型

    有什么方法可以从 NativeActivity 中查看其父 Activity 的类型Execute http msdn microsoft com en us library dd781091 aspx方法 是的 您可以执行以下代码块 它将
  • 带有请求的“单击”按钮

    我有一个小网站 我想用请求库填写表格 问题是我在填写表单数据并点击按钮时无法到达下一个站点 Enter 不起作用 重要的是我无法通过某种点击机器人来做到这一点 需要完成此操作 以便我可以在没有图形的情况下运行 info name JohnJ
  • Scrapy如何避免重新下载最近下载的媒体?

    根据https doc scrapy org en latest topics media pipeline html https doc scrapy org en latest topics media pipeline html Sc
  • C++中基类对象和派生类对象的大小

    include
  • .htaccess、Wordpress 和个性 URL

    我一直在研究我能在 WordPress 中的 htaccess 和虚荣 url 上找到的每个 Stack Overflow 主题 但我完全不明白为什么我的主题不起作用 我对 htaccess 完全是个菜鸟 所以我确信这与它有很大关系 我正在
  • Python:使用 chroot 和 chjail 保护不受信任的脚本/子进程?

    我正在编写一个基于 Python 的 Web 服务器 它应该能够执行 插件 以便可以轻松扩展功能 为此 我考虑了一种方法 即拥有多个文件夹 每个插件一个 和多个 shell python 脚本 其中以可能发生的不同事件的预定义名称命名 一个
  • c - “writev”中“iovcnt”参数允许的最大值?

    我读过手册页writev并发现错误部分指出 EINVAL 向量计数iovcnt小于零或大于允许的最大值 但我怎样才能得到最大值呢 PS 在我的操作系统 Ubuntu 14 04 x64 上它似乎是1024 我通过以下代码检查它 includ
  • 在 Android 中成功建立蓝牙连接

    我对 Android 中建立 BT 连接的两种方法感到困惑 从我记事起 这就是我所做的事情 它从 2 3 设备到早期的 4 x 都有效 这是什么Android 文档描述 http developer android com referenc
  • 来自removeObjectsInRange的NSRangeException:但传递的范围在边界内

    我收到下面的错误 这没有意义 由于未捕获的异常 NSRangeException 而终止应用程序 原因 NSMutableArray removeObjectsInRange 范围 11 15 超出范围 0 15 我在这里做错了什么 我在数
  • Java中关闭数据库连接

    我有点困惑了 我正在阅读以下内容Java 数据库连接 http en wikipedia org wiki Java Database Connectivity Connection conn DriverManager getConnec
  • 在 Azure 中从哪里获取 IssuerName 和 IssuerKey

    我正在关注这个tutorial http azure microsoft com en us documentation articles cloud services dotnet multi tier app using service
  • 在 Apache 中启用 css 和 js 文件的缓存

    在 Debian 8 2 上使用 Apache 2 4 我尝试启用所有 css 和 js 文件的缓存 图像缓存效果很好 也就是说 浏览器收到 304 状态 因此不会再次下载 但我无法缓存其他文件 我在虚拟主机文件中使用它
  • 为什么使用 ARKit 和 RealityKit 会出现这么多调试错误?

    在我的项目中 我只是包装了一个 ARView 设置了配置并在我的真实设备上运行它 当我启动应用程序 Xcode 时 打印出以下错误调试消息 2021 10 08 17 59 06 476537 0800 RealityKit Shell 8
  • Yii2环境文件夹的要点

    我正在尝试了解环境文件夹的意义是什么 最初我的想法是你可以将网络服务器指向不同的dev and prod文件夹中的environment文件夹 但读了一下之后我意识到情况并非如此 在 Yii 1 中你可以通过多个来解决这个问题index p
  • 如何以一般方式使 Python 函数运行的可执行文件的终端输出静音?

    我想抑制运行可执行文件的函数产生的所有终端输出 我尝试使用上下文管理器来抑制 Python 函数的输出 该上下文管理器在每次调用函数时临时重新定义 stdout 和 stderr 这抑制了由产生的终端输出print在函数中调用 但当函数调用