如何在Python 2.7中隐藏子进程的输出

ryp*_*pel 262 python subprocess espeak python-2.7

我在Ubuntu上使用eSpeak并且有一个Python 2.7脚本可以打印并说出一条消息:

import subprocess
text = 'Hello World.'
print text
subprocess.call(['espeak', text])
Run Code Online (Sandbox Code Playgroud)

eSpeak会产生所需的声音,但是外壳会出现一些错误(ALSA lib ...,没有套接字连接),因此我无法轻易读取之前打印的内容.退出代码为0.

不幸的是,没有任何记录的选项可以关闭它的详细程度,所以我正在寻找一种只能在视觉上使其静音并保持打开的外壳清洁以进行进一步交互的方法.

我怎样才能做到这一点?

jdi*_*jdi 398

将输出重定向到DEVNULL:

import os
import subprocess

FNULL = open(os.devnull, 'w')
retcode = subprocess.call(['echo', 'foo'], stdout=FNULL, stderr=subprocess.STDOUT)
Run Code Online (Sandbox Code Playgroud)

它实际上与运行此shell命令相同:

retcode = os.system("echo 'foo' &> /dev/null")
Run Code Online (Sandbox Code Playgroud)

  • micro quat picks:你可以使用`os.devnull`如果`subprocess.DEVNULL`不可用(<3.3),如果不检查返回的代码,请使用`check_call()`代替`call()`,打开对于`stdin/stdout/stderr`的二进制模式的文件,不鼓励使用`os.system()`,`&>`对于Ubuntu上的`sh`不起作用显式的`>/dev/null 2> &1`可以使用. (50认同)
  • 你不需要关闭你打开的FNULL吗? (13认同)
  • 只需注意,您可以在`subprocess.call`中使用`close_fds = True`在子进程存在后关闭`FNULL`描述符 (13认同)
  • @ewino:在`close_fds = True`上,文件描述符在*`fork()`之后关闭*但*在*`execvp()之前`ie,它们在*child*进程中关闭*在执行可执行文件之前*.如果任何流被重定向,[`close_fds = True`将无法在Windows上运行](https://www.python.org/dev/peps/pep-0446/#inheritance-of-file-descriptors-on-视窗).`close_fds`不会关闭*parent*进程中的文件. (7认同)
  • @JFSebastian:感谢您的建议。我实际上想使用 `os.devnull` 但不小心把它输入了。另外,我坚持使用“call”,因为他们没有捕获“check_call”可能引发的异常。对于“os.system”重定向,它更多地只是说明了有效使用子流程方法的作用。并不是真正的第二个建议。 (2认同)

jfs*_*jfs 85

这是一个更便携的版本(只是为了好玩,在你的情况下没有必要):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from subprocess import Popen, PIPE, STDOUT

try:
    from subprocess import DEVNULL # py3k
except ImportError:
    import os
    DEVNULL = open(os.devnull, 'wb')

text = u"René Descartes"
p = Popen(['espeak', '-b', '1'], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT)
p.communicate(text.encode('utf-8'))
assert p.returncode == 0 # use appropriate for your program error handling here
Run Code Online (Sandbox Code Playgroud)

  • 注意,这会产生一个'DEVNULL`,它不是完全通用的,就像`subprocess`提供的那样; 因为它打开`wb`它不能用于`stdin`. (4认同)
  • @jfs 8年后我们只是做`stdout=subprocess.DEVNULL`,对吧? (3认同)

Zag*_*ags 28

使用subprocess.check_output(python 2.7中的新增功能).如果命令失败,它将禁止stdout并引发异常.(它实际上返回了stdout的内容,因此如果需要,可以稍后在程序中使用它.)示例:

import subprocess
try:
    subprocess.check_output(['espeak', text])
except subprocess.CalledProcessError:
    # Do something
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下内容来抑制stderr:

    subprocess.check_output(["espeak", text], stderr=subprocess.STDOUT)
Run Code Online (Sandbox Code Playgroud)

对于早于2.7,使用

import os
import subprocess
with open(os.devnull, 'w')  as FNULL:
    try:
        subprocess._check_call(['espeak', text], stdout=FNULL)
    except subprocess.CalledProcessError:
        # Do something
Run Code Online (Sandbox Code Playgroud)

在这里,您可以使用抑制stderr

        subprocess._check_call(['espeak', text], stdout=FNULL, stderr=FNULL)
Run Code Online (Sandbox Code Playgroud)


Jos*_*eia 11

由于Python3的你不再需要打开devnull并且可以调用subprocess.DEVNULL.

您的代码将更新为:

import subprocess
text = 'Hello World.'
print(text)
subprocess.call(['espeak', text], stderr=subprocess.DEVNULL)
Run Code Online (Sandbox Code Playgroud)

  • 作品!此外,可以在上面的代码中将“stderr”与“stdout”交换(或附加为另一个参数)以抑制输出。“输出”位于问题的标题中,是什么导致我来到这里......也许微不足道,但认为值得一提。 (2认同)