Exception ignored in: <function AbstractConnection.__del__ at 0x> RuntimeError: Event loop is closed

给FastAPI项目做单元测试时(app的lifespan挂载了异步redis),控制台打印了如下信息:

Exception ignored in: <function AbstractConnection.__del__ at 0x7fca80112700>
Traceback (most recent call last):
  File "/home/grap/.cache/pypoetry/virtualenvs/stream-formatter-7CmN-bn6-py3.11/lib/python3.11/site-packages/redis/asyncio/connection.py", line 216, in __del__
    self._close()
  File "/home/grap/.cache/pypoetry/virtualenvs/stream-formatter-7CmN-bn6-py3.11/lib/python3.11/site-packages/redis/asyncio/connection.py", line 223, in _close
    self._writer.close()
  File "/usr/local/lib/python3.11/asyncio/streams.py", line 355, in close
    return self._transport.close()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 860, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 761, in call_soon
    self._check_closed()
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 519, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function AbstractConnection.__del__ at 0x7fca80112700>
Traceback (most recent call last):
  File "/home/grap/.cache/pypoetry/virtualenvs/stream-formatter-7CmN-bn6-py3.11/lib/python3.11/site-packages/redis/asyncio/connection.py", line 216, in __del__
    self._close()
  File "/home/grap/.cache/pypoetry/virtualenvs/stream-formatter-7CmN-bn6-py3.11/lib/python3.11/site-packages/redis/asyncio/connection.py", line 223, in _close
    self._writer.close()
  File "/usr/local/lib/python3.11/asyncio/streams.py", line 355, in close
    return self._transport.close()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 860, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 761, in call_soon
    self._check_closed()
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 519, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function AbstractConnection.__del__ at 0x7fca80112700>
Traceback (most recent call last):
  File "/home/grap/.cache/pypoetry/virtualenvs/stream-formatter-7CmN-bn6-py3.11/lib/python3.11/site-packages/redis/asyncio/connection.py", line 216, in __del__
    self._close()
  File "/home/grap/.cache/pypoetry/virtualenvs/stream-formatter-7CmN-bn6-py3.11/lib/python3.11/site-packages/redis/asyncio/connection.py", line 223, in _close
    self._writer.close()
  File "/usr/local/lib/python3.11/asyncio/streams.py", line 355, in close
    return self._transport.close()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 860, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 761, in call_soon
    self._check_closed()
  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 519, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

其中fastapi服务main.py代码大致如下:

from contextlib import asynccontextmanager
from fastapi import FastAPI
from redis.asyncio import Redis


@asynccontextmanager
async def lifespan(app):
    app.state.redis = Redis()
    yield
    await app.state.redis.aclose()


app = FastAPI(lifespan=lifespan)

conftest.py主要代码如下:

from pathlib import Path

import pytest
from asgi_lifespan import LifespanManager
from httpx import ASGITransport, AsyncClient

from main import app


@pytest.fixture(scope="session")
def anyio_backend():
    return "asyncio"


@pytest.fixture(scope="session")
async def client():
    async with LifespanManager(app) as manager:
        transport = ASGITransport(app=manager.app)  # type:ignore[arg-type]
        async with AsyncClient(transport=transport, base_url="http://test") as client:
            yield client

原因:跟这个类似Not waiting for connection_lost() when transport closed · Issue #1925 · aio-libs/aiohttp · GitHub

解决:参考了这个"RuntimeError: Event loop is closed" when ProactorEventLoop is used · Issue #4324 · aio-libs/aiohttp · GitHub

在conftest.py文件里,开头增加import asyncio,结尾增加如下几行:

origin_shutdown = asyncio.BaseEventLoop.shutdown_default_executor


async def _shutdown(self):
    await origin_shutdown(self)
    await asyncio.sleep(5)


asyncio.BaseEventLoop.shutdown_default_executor = _shutdown  # type:ignore

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值