Python 禁止在库外部调用模块的输出
我在使用机器学习库时遇到了一个恼人的问题。PyML用于训练SVM分类器。问题是libsvm将一些文本输出到标准输出。但因为这是Python之外的,所以我无法拦截它。我尝试使用问题中描述的方法,但这些方法都没有帮助Python 禁止在库外部调用模块的输出,python,libsvm,pyml,Python,Libsvm,Pyml,我在使用机器学习库时遇到了一个恼人的问题。PyML用于训练SVM分类器。问题是libsvm将一些文本输出到标准输出。但因为这是Python之外的,所以我无法拦截它。我尝试使用问题中描述的方法,但这些方法都没有帮助 有没有办法做到这一点。修改PyML不是一个选项。Open/dev/null要编写,请使用os.dup()复制标准输出,并使用os.dup2()将打开的/dev/null复制到标准输出。使用os.dup2()将复制的标准输出复制回实际的标准输出 devnull = open('/dev/
有没有办法做到这一点。修改PyML不是一个选项。Open
/dev/null
要编写,请使用os.dup()
复制标准输出,并使用os.dup2()
将打开的/dev/null
复制到标准输出。使用os.dup2()
将复制的标准输出复制回实际的标准输出
devnull = open('/dev/null', 'w')
oldstdout_fno = os.dup(sys.stdout.fileno())
os.dup2(devnull.fileno(), 1)
makesomenoise()
os.dup2(oldstdout_fno, 1)
我也遇到了同样的问题,并这样修复了它:
from cStringIO import StringIO
def wrapped_svm_predict(*args):
"""Run :func:`svm_predict` with no *stdout* output."""
so, sys.stdout = sys.stdout, StringIO()
ret = svm_predict(*args)
sys.stdout = so
return ret
戴夫·史密斯在他的演讲中给出了一个极好的答案。基本上,它很好地包装了Ignacio的答案:
def suppress_stdout():
with open(os.devnull, "w") as devnull:
old_stdout = sys.stdout
sys.stdout = devnull
try:
yield
finally:
sys.stdout = old_stdout
现在,您可以将任何将不需要的噪声散播到标准输出中的函数包围起来,如下所示:
print "You can see this"
with suppress_stdout():
print "You cannot see this"
print "And you can see this again"
对于Python 3,您可以使用:
from contextlib import contextmanager
import os
import sys
@contextmanager
def suppress_stdout():
with open(os.devnull, "w") as devnull:
old_stdout = sys.stdout
sys.stdout = devnull
try:
yield
finally:
sys.stdout = old_stdout
我在portaudio/PyAudio初始化时遇到了类似的问题。我从里德的回答开始,这很有效。尽管我需要重定向stderr。因此,这里是一个更新的跨平台版本,它重定向了以下两个方面:
import sys, os
# hide diagnostic output
with open(os.devnull, 'w') as devnull:
# suppress stdout
orig_stdout_fno = os.dup(sys.stdout.fileno())
os.dup2(devnull.fileno(), 1)
# suppress stderr
orig_stderr_fno = os.dup(sys.stderr.fileno())
os.dup2(devnull.fileno(), 2)
print('*** stdout should be hidden! ****')
print('*** stderr should be too! ****',
file=sys.stderr)
os.dup2(orig_stdout_fno, 1) # restore stdout
os.dup2(orig_stderr_fno, 2) # restore stderr
print('done.')
应该很容易注释出您不需要的零件。您检查过了吗,也许它写在sys.stderr而不是sys.stdout中!!!相关:--本例中的文件是
os.devnull
。'oldstdout=os.dup(sys.stdout)'throws a typeerror'a integer is required'计算出来,sys.stdout.fileno()和devnull.fileno()是必需的,在这之后可以工作,谢谢!!你是不是应该在结尾用devnull.close()
关闭devnull,还是用with
语句打开它?里德,你的答案对我来说仍然不适用。我需要一个os.fsync(devnull.fileno())
在最后一次dup2调试之前,尝试import pybullet as pb
作为您想要静音的东西:)如果输出来自python,这将起作用,但如果它来自python调用的共享库,我相信这就是OP所要问的。对我来说,它使用了libsvm的Python绑定。我想PyML的情况也差不多。Stdout是一个进程属性,即只要不通过子进程使用外部功能,我的包装(以及Ignacio的解决方案)就可以完美地工作。只有当有人打开/dev/stdout
将输出写入时,它才会失败。这正是大多数共享库所做的,这就是为什么此解决方案不适用于大多数人。上面的解决方案将更接近请求者的需求。这些解决方案只能抑制python中产生的输出。可能是的。此外,我发现该解决方案无法抑制某些python输出,例如TQM进度条即使在该上下文中也能成功打印到标准输出,但不确定原因。尽管如此,我还是发现在Python中的大多数情况下,它都是有效的。默认情况下,TQDM progressbar会打印到stderr以抑制它。您还需要重定向sys.stderr