FAILED tests/test_network.py::test_connect - pytest.PytestUnraisableExceptionWarning: 忽略的异常:<socket.socket fd=5> ResourceWarning: 未关闭的 <socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 54321), raddr=('127.0.0.1', 8080)>
FAILED tests/test_network.py::test_connect - pytest.PytestUnraisableExceptionWarning: Exception ignored in: <socket.socket fd=5> ResourceWarning: unclosed <socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 54321), raddr=('127.0.0.1', 8080)>
ID: python/pytest-warnings-as-errors-unclosed-socket
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| 7.x | active | — | — | — |
| 8.x | active | — | — | — |
根因分析
pytest 配置了 filterwarnings = error,因此未关闭的 socket(例如 fixture 或测试中未关闭的连接)产生的 ResourceWarning 被提升为错误并导致测试失败。
English
pytest is configured with filterwarnings = error, so ResourceWarning from an unclosed socket (e.g., a connection not closed in a fixture or test) is promoted to an error and fails the test.
解决方案
-
95% 成功率
import socket import pytest @pytest.fixture def conn(): s = socket.create_connection(('127.0.0.1', 8080)) yield s s.close() def test_connect(conn): ... -
90% 成功率
from contextlib import closing def test_connect(): with closing(socket.create_connection(('127.0.0.1', 8080))) as s: ...
无效尝试
常见但无效的做法:
-
70% 失败
Hides real resource leaks in production code and can mask other warnings-as-errors that you do want to catch.
-
65% 失败
gc.collect() may run before the socket's __del__ or may not close the socket deterministically; the warning can still fire during interpreter shutdown.