我想禁止运行可执行程序的函数产生的所有终端输出。
我试图通过使用上下文管理器来抑制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
我想抑制该输出。
编辑:测试由@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
或的终端输出ls
,我不确定为什么。
您可以从PyAudio切换到sounddevice模块,该模块已经负责使终端输出静音(请参阅#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/
。
更新:
上面的上下文管理器使标准错误输出(stderr
)静音,该错误用于原始问题中提到的来自PortAudio的烦人消息。如要删除标准输出(stdout
),就像在更新的问题中一样,您必须将替换sys.stderr
为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)
我已经能够使用pyInstaller从Python 3.4代码成功地生成Windows可执行文件。 但是,每次运行可执行文件(控制台应用程序)时,它都会在代码启动前输出以下内容: 我假设这是pyInstaller引导加载程序过程,如下所述。我想知道是否有一种方法可以抑制这个输出,而不抑制我自己的Python代码生成的输出? 附加信息: 生成单个可执行文件(使用选项) 运行在Windows 7 En
问题内容: 我有一个名为’a’的二进制文件,它在被调用时生成输出。如果我从 在bashshell中,大部分输出被“a>/dev/null”抑制。所有的 输出被 我有一个名为“B”的python脚本,需要调用“a”。我希望能够 从“B”生成输出,同时禁止从“A”生成所有输出。 在“B”中,我试过, 以及,等等,但这些都不是 抑制A的所有输出。 我可以运行’B&>/dev/null’,但这也会抑制’B
问题内容: 我是Unix环境的新手。 我想要一个小的聊天程序,将初始终端用于输入,并调用另一个终端进行输出。我一直在网上搜索,但没有任何运气。 好的,更具体地说,我正在C中的Mac上通过TCP / IP编写聊天程序。我想在两个不同的终端中分离输入和聊天消息输出。我可以找到有关如何在进程之间进行通信的资源,但是我不知道如何为输出调用另一个终端。 问题答案: 以您似乎正在做的方式生成另一个终端是非常不
从Eclipse导出可运行的JAR文件是从另一台机器上的命令行启动Eclipse项目的最快方法。请参见此答案。 问题是,如果要从中运行的计算机上安装的JRE比Eclipse使用的JDK旧,则会出现以下错误: 我知道,在Eclipse上,我可以用较低的遵从性级别(例如,用1.6而不是1.7)构建项目,但这似乎不会影响导出的JAR文件。 关于如何导出要在旧JRE上执行的Runnable JAR文件的任
好的,所以基本上,每次我看到这个问题被问到,它都没有我想要的答案,这就是为什么我要问自己。 基本上,我在BlueJ上做了一个java项目(遗憾的是,学校要求。但如果这是个问题,我可以将它导出到其他地方(最好是IntelliJ或Visual Studio代码)),但本质上,我想这样做,我只需双击我的.jar导出,它就会打开一个终端窗口并启动。然而,当我尝试这个方法时,我得到了这个错误:第一个错误 当
终端中使用lldb运行可执行文件 进入lldb环境, 在终端内输入lldb回车 lldb 使用file命令, 将可执行文件包装成一个target (lldb) file test Current executable set to '/Users/shenyj/Documents/CodeForTest/staticOCLib/test' (x86_64). 运行可执行文件, 在刚刚的l