If I take a simple test script like this, which results in ResourceWarning:
import asyncio
import aiohttp
async def main():
client = aiohttp.ClientSession()
await client.get("https://google.com")
asyncio.run(main())
Run it with python -bb -We -X dev test.py
.
I'm expecting the ResourceWarning
to error and result in a non-0 exit code.
Actual result:
Exception ignored in: <function ClientSession.__del__ at 0x7f397e04beb0>
Traceback (most recent call last):
File "/home/s/.local/lib/python3.8/site-packages/aiohttp/client.py", line 342, in __del__
_warnings.warn(
ResourceWarning: Unclosed client session <aiohttp.client.ClientSession object at 0x7f397dfce4b0>
Exception ignored in: <function BaseConnector.__del__ at 0x7f397e0b6eb0>
Traceback (most recent call last):
File "/home/s/.local/lib/python3.8/site-packages/aiohttp/connector.py", line 281, in __del__
_warnings.warn(f"Unclosed connector {self!r}", ResourceWarning, **kwargs)
ResourceWarning: Unclosed connector <aiohttp.connector.TCPConnector object at 0x7f397dfce690>
Exception ignored in: <socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.1.18', 45750), raddr=('172.217.169.4', 443)>
ResourceWarning: unclosed <socket.socket fd=7, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.1.18', 45750), raddr=('172.217.169.4', 443)>
Exception ignored in: <function _SelectorTransport.__del__ at 0x7f397e8264b0>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/selector_events.py", line 696, in __del__
_warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
ResourceWarning: unclosed transport <_SelectorSocketTransport fd=7>
Exception ignored in: <function _SelectorTransport.__del__ at 0x7f397e8264b0>
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/selector_events.py", line 696, in __del__
_warn(f"unclosed transport {self!r}", ResourceWarning, source=self)
ResourceWarning: unclosed transport <_SelectorSocketTransport fd=6>
Exception ignored in: <socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.1.18', 42986), raddr=('142.250.187.206', 443)>
ResourceWarning: unclosed <socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.1.18', 42986), raddr=('142.250.187.206', 443)>
0 exit code indicating success.
How do I ensure the program actually fails on a warning?
-We
makes the interpreter raise an exception instead of a warning. However, within the __del__
function no exception can be raised. Instead, such exceptions are printed to the stderr and the execution continues. This behavior can be overridden via sys.unraisablehook
.
Here's a modified version of the code that will return non-zero exit code:
import aiohttp
import asyncio
import os
import sys
def custom_hook(args):
os._exit(7)
async def main():
client = aiohttp.ClientSession()
await client.get("https://google.com")
sys.unraisablehook = custom_hook
asyncio.run(main())
Notice that instead of sys.exit()
I use os._exit()
. That's because sys.exit()
raises SystemExit exception which is a bad idea in our case.