子进程,stderr 到 DEVNULL 但打印错误
Subprocess, stderr to DEVNULL but errors are printed
我正在使用 python 开发法语聊天机器人。对于第一次文本到语音的尝试,我将 espeak 与 mbrola 结合使用。我用子进程调用它:
from subprocess import run, DEVNULL
def speak(text):
command = ["espeak", "-vmb-fr1", text]
run(command, stderr=DEVNULL, stdout=DEVNULL)
speak("Bonjour.")
如您所见,我将 stderr 和 stdout 发送到 /dev/null
当我 运行 程序时,它似乎可以工作,espeak 正在说话,但我得到这个 :
*** Error in `mbrola': free(): invalid pointer: 0x08e3af18 ***
*** Error in `mbrola': free(): invalid pointer: 0x0988af88 ***
我认为是mbrola 中的C 错误。我想我无法修复它。但它有效,所以我只想消除错误。我能怎么做 ?有办法吗?
编辑,回应:
当我通过 shell (python myscript.py 2>&1 >/dev/null
) 重定向 stdout 和 stderr 时,消息仍然显示。
- 发行版:Debian 9.3
- glibc 版本:2.24
运行它跟setsid
(just add that string in front of the command and arguments). That will stop it from opening /dev/tty
to report the malloc errors. It will also prevent terminal signals一样,包括SIGHUP
当终端关闭时,不影响进程,这可能是好事也可能是坏事。
或者,将环境变量 LIBC_FATAL_STDERR_
设置为 some nonempty string, with whose name I was able to find questions。
根本问题是 mbrola
/espeak
在内存分配方面存在严重错误。如果您还没有检查新版本,并向他们报告了错误,那是您应该做的第一件事。
这些警告由 glibc 的 malloc 检查器发出,在 mallopt
文档中有描述。如果启用堆检查,每个检测到的 malloc
(以及 free
和相关函数)的错误都将被打印到 stderr,但如果它被禁用,则什么也不会做。 (也可以使用其他可能性,但这与此处无关。)
根据文档,除非程序显式调用 mallopt
,否则将环境变量 MALLOC_CHECK_
设置为 0 或根本不设置它应该意味着没有 malloc 调试输出。然而,大多数主要发行版(从 Debian 开始)长期以来都提供了一个 glibc
,它被配置为默认值 1(意味着打印错误消息)而不是 0。您仍然可以通过显式设置 MALLOC_CHECK_=0
.
此外,文档暗示除非 malloc_printerr
被替换,否则 malloc 错误会转到 stderr
。但同样,许多发行版确实用一个故意更难忽略的函数替换它,如果假装则记录到当前进程的 tty,否则记录到 stderr。这就是为什么即使您将 espeak
的 stderr 和您自己的程序通过管道传输到 /dev/null 也会显示的原因。
因此,要隐藏这些错误,您可以:
- 在
espeak
中将环境变量 MALLOC_CHECK_
设置为 0,这将禁用检查。
- 防止
espeak
打开一个tty,这意味着检查仍然会发生,但输出将无处可去。
在新进程开始时使用 setsid
, a tool that calls setsid
是实现后者的一种方法。这是否是一个好主意取决于您是否希望流程领导其自己的流程组。你真的应该仔细阅读这意味着什么并决定你想要什么,而不是在选项之间进行选择,因为输入 setsid
比输入 MALLOC_CHECK_=0
.
更短
再说一次,你真的应该先检查一个新版本,如果他们还没有修复这个错误,请向上游报告。
我正在使用 python 开发法语聊天机器人。对于第一次文本到语音的尝试,我将 espeak 与 mbrola 结合使用。我用子进程调用它:
from subprocess import run, DEVNULL
def speak(text):
command = ["espeak", "-vmb-fr1", text]
run(command, stderr=DEVNULL, stdout=DEVNULL)
speak("Bonjour.")
如您所见,我将 stderr 和 stdout 发送到 /dev/null
当我 运行 程序时,它似乎可以工作,espeak 正在说话,但我得到这个 :
*** Error in `mbrola': free(): invalid pointer: 0x08e3af18 ***
*** Error in `mbrola': free(): invalid pointer: 0x0988af88 ***
我认为是mbrola 中的C 错误。我想我无法修复它。但它有效,所以我只想消除错误。我能怎么做 ?有办法吗?
编辑,回应
当我通过 shell (python myscript.py 2>&1 >/dev/null
) 重定向 stdout 和 stderr 时,消息仍然显示。
- 发行版:Debian 9.3
- glibc 版本:2.24
运行它跟setsid
(just add that string in front of the command and arguments). That will stop it from opening /dev/tty
to report the malloc errors. It will also prevent terminal signals一样,包括SIGHUP
当终端关闭时,不影响进程,这可能是好事也可能是坏事。
或者,将环境变量 LIBC_FATAL_STDERR_
设置为 some nonempty string, with whose name I was able to find
根本问题是 mbrola
/espeak
在内存分配方面存在严重错误。如果您还没有检查新版本,并向他们报告了错误,那是您应该做的第一件事。
这些警告由 glibc 的 malloc 检查器发出,在 mallopt
文档中有描述。如果启用堆检查,每个检测到的 malloc
(以及 free
和相关函数)的错误都将被打印到 stderr,但如果它被禁用,则什么也不会做。 (也可以使用其他可能性,但这与此处无关。)
根据文档,除非程序显式调用 mallopt
,否则将环境变量 MALLOC_CHECK_
设置为 0 或根本不设置它应该意味着没有 malloc 调试输出。然而,大多数主要发行版(从 Debian 开始)长期以来都提供了一个 glibc
,它被配置为默认值 1(意味着打印错误消息)而不是 0。您仍然可以通过显式设置 MALLOC_CHECK_=0
.
此外,文档暗示除非 malloc_printerr
被替换,否则 malloc 错误会转到 stderr
。但同样,许多发行版确实用一个故意更难忽略的函数替换它,如果假装则记录到当前进程的 tty,否则记录到 stderr。这就是为什么即使您将 espeak
的 stderr 和您自己的程序通过管道传输到 /dev/null 也会显示的原因。
因此,要隐藏这些错误,您可以:
- 在
espeak
中将环境变量MALLOC_CHECK_
设置为 0,这将禁用检查。 - 防止
espeak
打开一个tty,这意味着检查仍然会发生,但输出将无处可去。
在新进程开始时使用 setsid
, a tool that calls setsid
是实现后者的一种方法。这是否是一个好主意取决于您是否希望流程领导其自己的流程组。你真的应该仔细阅读这意味着什么并决定你想要什么,而不是在选项之间进行选择,因为输入 setsid
比输入 MALLOC_CHECK_=0
.
再说一次,你真的应该先检查一个新版本,如果他们还没有修复这个错误,请向上游报告。