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用于训练SVM分类器。问题是libsvm将一些文本输出到标准输出。但因为这是Python之外的,所以我无法拦截它。我尝试使用问题中描述的方法,但这些方法都没有帮助


有没有办法做到这一点。修改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