将Python 3 ResourceWarnings转换为异常

A. *_*vis 7 python python-3.x

有没有办法强制Python 3 unittest失败,而不是简单地向stderr发出警告,如果它导致任何ResourceWarning?

我尝试过以下方法:

import warnings
warnings.simplefilter(action='error', category=ResourceWarning)
Run Code Online (Sandbox Code Playgroud)

这导致unittest的输出:

my_test (__main__.MyTest) ... Exception ignored in: <socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 54065), raddr=('127.0.0.1', 27017)>
ResourceWarning: unclosed <socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 54065), raddr=('127.0.0.1', 27017)>
ok

----------------------------------------------------------------------
Ran 1 test in 0.110s
Run Code Online (Sandbox Code Playgroud)

请注意"忽略异常"消息.我宁愿测试失败,而不是要求我阅读其输出,寻找ResourceWarnings.

jfs*_*jfs 6

如果ResourceWarningwith catch_warning()语句中的代码生成,则单元测试失败:

#!/usr/bin/env python3
import gc
import socket
import unittest
import warnings

class Test(unittest.TestCase):
    def test_resource_warning(self):
        s = socket.socket()
        ####s.close() #XXX uncomment to pass the test

        # generate resource warning when s is deleted
        with warnings.catch_warnings(record=True) as w:
            warnings.resetwarnings() # clear all filters
            warnings.simplefilter('ignore') # ignore all
            warnings.simplefilter('always', ResourceWarning) # add filter
            del s        # remove reference
            gc.collect() # run garbage collection (for pypy3)
            self.assertFalse(w and str(w[-1])) # test fails if there
                                               # are warnings

if __name__=="__main__":
    unittest.main()
Run Code Online (Sandbox Code Playgroud)


Dan*_*ing 5

不幸的是,这似乎不可能。“在忽略异常:”消息由CPython的函数产生PyErr_WriteUnraisablePython/errors.c。该函数之前的评论指出:

/* Call when an exception has occurred but there is no way for Python
   to handle it.  Examples: exception in __del__ or during GC. */
Run Code Online (Sandbox Code Playgroud)

ResourceWarning确实正在垃圾收集过程中产生的,因为它并没有以此来提高在这一点上异常的Python打印消息。这与核心 CPython 实现有关,并且 unittest 无法覆盖它。

更新:虽然以上是正确的技术分析,但还有另一种方法可以实际解决 OP 的问题。有关更多详细信息,请参阅JF Sebastian的回答