禁用 Python 3.2 资源警告

Posted

技术标签:

【中文标题】禁用 Python 3.2 资源警告【英文标题】:Disabling Python 3.2 ResourceWarning 【发布时间】:2014-10-25 14:53:55 【问题描述】:

Python 3.2 为未关闭的系统资源(网络套接字、文件)引入了ResourceWarning

虽然代码在生产环境中运行良好,但在运行单元测试时,由于使用了出现警告的第三方库,我收到了很多以下警告。我可以修复该库,但另一方面,在测试运行期间忽略它要简单得多。

 block_io-python/block_io/__init__.py:182: ResourceWarning: unclosed <ssl.SSLSocket fd=11, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=6, laddr=('x', 58395), raddr=('x, 443)>

禁用这些警告的方法是什么?我尝试了以下但没有效果:

 warnings.filterwarnings("ignore", category=ResourceWarning)

(在单元测试导入期间运行)。

【问题讨论】:

如果明显的行为不起作用并且我不知道我做错了什么,也许我可以被允许? :) 可能是发出警告的模块正在使用warnings.showwarning。该功能似乎绕过了警告过滤器。 也许第三方代码还添加了一个warnings.filterwarnings('default', category=ResourceWarning),它会通过放在它前面来覆盖您的代码?如果@Dunes 理论是正确的,您可以在上下文管理器with warnings.catch_warnings(): 中覆盖warnings.showwarning @greschd:我将测试上下文管理器以排除其他人篡改警告的可能性。谢谢你的想法。 fossies.org/dox/Python-3.4.2/socketmodule_8c_source.html 中的第 3855 行是发出警告的位置。在我看来一切都很好。可能的问题是测试工具正在消除模块的__warningregistry__,或者您正在使用在调试模式下编译的python。只有在调试模式下编译 python 时,才会默认显示资源警告。也许在调试模式下无法隐藏警告... 【参考方案1】:

我找到了罪魁祸首。您说您在导入时设置了过滤器。但是,从 Python 3.2 开始,单元测试模块已更新为将警告过滤器设置为默认值。见Section 29.5.5。基本上,unittest 在完成模块导入后会覆盖您的警告过滤器首选项。

例如。

my_tests.py

import socket
import unittest
import warnings

warnings.simplefilter("ignore", ResourceWarning)

def abusesocket():
    s = socket.socket()
    s.connect(("www.google.com", 80))

class Test(unittest.TestCase):

    def test1(self):
        print("test1")
        abusesocket()
        print("module import warning filter nixed")

    def test2(self):
        print("test2")
        warnings.simplefilter("ignore", ResourceWarning)
        abusesocket()
        print("higher warning filter okay")

给出以下输出

$ python3 -m unittest  my_tests.py 
test1
/home/user/my_tests.py:15: ResourceWarning: unclosed <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=0, laddr=('x.x.x.x', 52332), raddr=('31.55.166.217', 80)>
  abusesocket()
module import warning filter nixed
.test2
higher warning filter okay
.
----------------------------------------------------------------------
Ran 2 tests in 0.347s

OK

解决方案

unittest 似乎会在每次测试后重置警告过滤器。因此,您将在每次测试开始时清除过滤器。可能最好使用装饰器来包装您的测试函数。

def ignore_warnings(test_func):
    def do_test(self, *args, **kwargs):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", ResourceWarning)
            test_func(self, *args, **kwargs)
    return do_test

class Test(unittest.TestCase):

    @ignore_warnings
    def test1(self):
        abusesocket()

【讨论】:

您也可以将它放在def setUp(self): 中,以便在整个测试用例中持续使用。 我们需要定义一个ignore_warnings() 函数来禁用警告吗? 没有。这只是一种方法。 @ThomasAhle 提出了将过滤器放在 setup 中的好处。 好吧,您的解决方案不适用于 python 3.6.5。有什么想法吗? @Dunes 你能在setUp 中指出如何做到这一点吗,这是否使用上下文管理器......你能在你的答案中添加这一点吗?【参考方案2】:

unittest.main(warnings='ignore')

【讨论】:

您的解决方案非常优雅,但如何使其运行测试:python setup.py test【参考方案3】:

这个替代方案对我有用:

    def setUp(self):
        if not sys.warnoptions:
            import warnings
            warnings.simplefilter("ignore")

见:Standard Library docs - Overriding the default filter

【讨论】:

【参考方案4】:

我用它在测试前只禁用 ResourceWarning 警告,然后重新启用它。


import unittest
import warnings

class MyTestCase(unittest.TestCase):

    def setUp(self):
        warnings.simplefilter("ignore", ResourceWarning)

    def tearDown(self):
        warnings.simplefilter("default", ResourceWarning)

另见:Different options besides "default" and "ignore"

【讨论】:

【参考方案5】:

在类级别为所有方法设置一次似乎比作为实例级别的 setUp() 重复更有效:

    @classmethod
    def setUpClass(cls):
        warnings.simplefilter("ignore")

【讨论】:

以上是关于禁用 Python 3.2 资源警告的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用python警告

VS Code - 我可以禁用“无 Python 解释器”警告吗?

关闭vs警告

Python的Request模块,请求跳过认证及禁用警告

如何禁用 Pylint 警告?

如何为生成的 service worker 禁用 workbox-webpack-plugin 的警告