我正在使用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错误。我想我无法修复它。但它确实有效,所以我只想将错误静音。我能怎么做 ?有办法吗?
编辑,以回复abarnert:
当我通过shell(python myscript.py 2>&1 >/dev/null
)重定向stdout和stderr时,消息仍然显示。
答案 0 :(得分:2)
使用setsid
运行它(只需在命令和参数前添加该字符串)。这将阻止它打开/dev/tty
来报告malloc错误。当终端关闭时,它还会阻止terminal signals(包括SIGHUP
)影响流程,这可能是好事还是坏事。
或者,将环境变量LIBC_FATAL_STDERR_
设置为some nonempty string,我的名称可以找到several similar questions。
答案 1 :(得分:1)
根本问题是mbrola
/ espeak
存在严重的内存分配错误。如果您还没有检查过新版本,并向他们报告错误,那么您应该做的第一件事。
这些警告是由glibc的malloc检查程序发出的,mallopt
文档中对此进行了描述。如果启用了堆检查,则每个检测到的malloc
(以及free
和相关函数)的错误都将打印到stderr,但如果它被禁用,则不会执行任何操作。 (也有其他可能性,但这里没有相关性。)
根据文档,除非程序显式调用mallopt
,否则将环境变量MALLOC_CHECK_
设置为0或者根本不设置它应该意味着没有malloc调试输出。但是,大多数主要的发行版(从Debian开始)长期以来已经将glibc
配置为默认为1(意味着打印错误消息)而不是0.您仍然可以通过显式设置来覆盖它MALLOC_CHECK_=0
。
此外,文档暗示malloc错误转到stderr
,除非替换malloc_printerr
。但同样,许多发行版确实用一个故意难以忽略的功能取而代之,如果没有假装,则会记录到当前进程的tty和tderr。这就是为什么即使你将espeak
的stderr传递给/ dev / null,以及你自己的程序也是如此。
因此,要隐藏这些错误,您可以:
MALLOC_CHECK_
中将环境变量espeak
设置为0,这将禁用检查。espeak
打开tty,这意味着检查仍然会发生,但输出无处可去。使用setsid
,一个在新进程开始时调用setsid
的工具,是执行后者的一种方法。这是否是个好主意取决于您是否希望流程引导其自己的流程组。你真的应该阅读这意味着什么并决定你想要什么,而不是选择选项,因为输入setsid
比输入MALLOC_CHECK_=0
要短。
而且,你真的应该首先检查一个新版本,如果他们尚未修复它,请向上游报告此错误。