如何使用warnings.filterwarnings来抑制第三方警告

67

我在我的Python代码中使用Paramiko(用于SFTP)。除了每次导入或调用Paramiko函数时都会出现以下警告之外,一切正常:

C:\Python26\lib\site-packages\Crypto\Util\randpool.py:40: RandomPool_Deprecation
Warning: This application uses RandomPool, which is BROKEN in older releases.  S
ee http://www.pycrypto.org/randpool-broken
  RandomPool_DeprecationWarning)
我知道这与Paramiko使用PyCrypto的一些不推荐功能有关。我的问题是,是否有办法以编程方式抑制此警告?我尝试过这个:
warnings.filterwarnings(action='ignore', \
category=DeprecationWarning, module='paramiko')

甚至还有这个:

warnings.filterwarnings(action='ignore', \
category=DeprecationWarning, module='randpool')

在'import paramiko'语句之前以及paramiko特定函数调用之前添加以下代码,可以消除这个警告。但是无论如何都会出现这个警告。

如果有帮助的话,这是打印警告的第三方库中的代码:

from Crypto.pct_warnings import RandomPool_DeprecationWarning
import Crypto.Random
import warnings

class RandomPool:
    """Deprecated.  Use Random.new() instead.

    See http://www.pycrypto.org/randpool-broken
    """
    def __init__(self, numbytes = 160, cipher=None, hash=None, file=None):
        warnings.warn("This application uses RandomPool, which is BROKEN in older releases.  See http://www.pycrypto.org/randpool-broken",
            RandomPool_DeprecationWarning)

如果您知道如何解决这个问题,请帮助我关闭此警告。

4个回答

67

最简单的方式是按照warnings模块在这里所建议的方法:

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    import paramiko

9
如何修改以仅过滤OP提到的特定警告? - VF1
@VF1 请查看Kyle的回答 - Oren Milman

29
warnings.filterwarningsmodule参数接受一个区分大小写的正则表达式,它应该与完全限定的模块名称匹配。因此,
warnings.filterwarnings(
    action='ignore',
    category=DeprecationWarning,
    module=r'.*randpool'
)
或者
warnings.filterwarnings(
    action='ignore',
    category=DeprecationWarning,
    module=r'Crypto\.Utils\.randpool'
)

应该可以工作。如果由于某些原因RandomPool_DeprecationWarning不是DeprecationWarning的子类,则可能需要显式编写RandomPool_DeprecationWarning而不是DeprecationWarning

您还可以通过在调用脚本时将-W选项传递给解释器来在命令行上禁用警告,如下所示:

$ python -W ignore::RandomPool_DeprecationWarning:Crypto.Utils.randpool: my_script.py
-W参数接受以action:message:category:module:lineno格式表达的过滤器,其中module必须严格匹配(完全限定)引发警告的模块名。
请参阅:https://docs.python.org/2/library/warnings.html?highlight=warnings#the-warnings-filterhttps://docs.python.org/2/using/cmdline.html#cmdoption-w

1
首先,import自定义警告,然后在category中使用它。 - Darren Weber

24

筛选特定的警告信息:

with warnings.catch_warnings():
    warnings.simplefilter('ignore', SpecificWarningObject)

    #do something that raises a Warning

已经有一段时间了,但我仍然想知道(并且没有一个好的答案):我该如何获取'SpecificWarningObject'对象? - tim654321
在这里,SpecificWarningObject只是一个占位符,用于过滤您想要忽略的任何警告。像这样做:from mymodule import SpecificWarningObject,并将“SpecificWarningObject”替换为您想要忽略的警告的名称。 - Kyle
啊,我明白替换对象的部分 - 但我不知道从哪里导入它?我正在寻找这两个警告: numpy \ lib \ function_base.py:2526:RuntimeWarning:切片自由度<=0 c = cov(x,y,rowvar) \numpy \ lib \ function_base.py:2455:RuntimeWarning:除以零遇到真正的除法c * = np.true_divide(1,fact) - tim654321
RuntimeWarning是一个内置的警告,因此您不需要导入任何内容。 - Kyle
但这将忽略所有的运行时警告,而非我担心的两个。 - tim654321
那么你需要使用 filterwarningsmessage 参数。 - Kyle

10
最灵活的方式是将warnings.filterwarnings()(或warnings.simplefilter())与warnings.catch_warnings()上下文管理器结合使用。这样,您既可以获得filterwarnings的灵活性,又可以将过滤器仅应用于with块内部。
import warnings

with warnings.catch_warnings():
    warnings.filterwarnings(
        action='ignore',
        category=SomeWarningClass,
        message='some message')
   
    # Do stuff that causes the warning


在文档中查看警告过滤器以获取filterwarnings参数的描述。

完整示例

这是一个带有自定义警告的完整示例:

import warnings

# Custom warning class for the example
class MyWarning(UserWarning):
    pass

def function_that_issues_warning(num):
    print(num)
    warnings.warn("This is a warning", MyWarning)


with warnings.catch_warnings():
    function_that_issues_warning(1) # issues warning
    warnings.filterwarnings(
        action="ignore", category=MyWarning, message="This is a warning"
    )

    function_that_issues_warning(2) # Warning is filtered
function_that_issues_warning(3) # issues warning


示例输出
1
.\test_warnings.py:10: MyWarning: This is a warning
  warnings.warn("This is a warning", MyWarning)
2
3
.\test_warnings.py:10: MyWarning: This is a warning
  warnings.warn("This is a warning", MyWarning)

1
嗨@np8,对我来说,使用warnings.simplefilter('ignore')而不是warnings.filterwarnings()(根据当前文档)可以使它正常工作。 - Mauricio Maroto
当您尝试使用warnings.filterwarnings()时发生了什么? - Niko Pasanen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接