You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

aiohttp服务GET请求返回500错误 loop参数异常修复方案

问题根因

你遇到的TypeError: BaseEventLoop.create_connection() got an unexpected keyword argument 'loop'是Python版本与旧版asyncio写法不兼容导致的:

Python 3.8 开始就将asyncio系列接口中显式传递loop的参数标记为废弃,到Python 3.10版本正式移除了该参数。你当前运行环境是Python 3.10,代码中多处手动传递loop参数的写法已经不被支持。

除此之外原代码还存在三个隐藏bug:

  • asyncio.open_connection本身是协程对象,原代码没有正确处理连接成功后的资源释放,会造成连接泄漏
  • 端口扫描区间使用range(begin_port, end_port)是左闭右开区间,传入1-10的参数实际只会扫描1-9端口,和预期不符
  • 异常捕获范围不全,仅捕获了TimeoutError,实际端口关闭时会抛出ConnectionRefusedError、OSError等异常,依然会触发500错误
修复步骤
  • 删除所有手动获取、传递event loop的冗余代码,Python 3.7+版本asyncio会自动绑定当前运行的事件循环,不需要手动传参
  • 修正端口检测逻辑,连接成功后主动关闭writer对象释放资源
  • 调整端口遍历的区间范围,将结束端口+1,保证扫描区间和传入参数一致
  • 补全异常捕获范围,移除不必要的asyncio.ensure_future冗余包装
  • 同步调整pytest用例适配新的代码逻辑
修复后完整代码
from aiohttp import web
import logging
import json
import asyncio


def catch_exception(func):
    async def decorated_function(ip, port):
        try:
            await func(ip, port)
            return {"port": str(port), "state": "open"}
        except (asyncio.TimeoutError, ConnectionRefusedError, OSError):
            return {"port": str(port), "state": "close"}
    return decorated_function


@catch_exception
async def check_port(ip, port):
    conn = asyncio.open_connection(ip, port)
    reader, writer = await asyncio.wait_for(conn, timeout=3)
    # 连接成功后主动关闭,避免资源泄漏
    writer.close()
    await writer.wait_closed()


async def run(ip, begin_port, end_port):
    tasks = [check_port(ip, p) for p in range(begin_port, end_port + 1)]
    responses = await asyncio.gather(*tasks)
    return responses


async def handle(request):
    ip = request.match_info.get('ip')
    begin_port = int(request.match_info.get('begin_port'))
    end_port = int(request.match_info.get('end_port'))

    results = await run(ip, begin_port, end_port)
    response_obj = {'data': results}

    return web.Response(text=json.dumps(response_obj), status=200, content_type='application/json')


def get_app():
    new_app = web.Application()
    new_app.router.add_get('/scan/{ip}/{begin_port}/{end_port}', handle)
    return new_app


# _________________________ pytest _____________________________________

def create_app():
    test_app = get_app()
    return test_app


async def test_hello(aiohttp_client):
    client = await aiohttp_client(create_app)
    resp = await client.get('/scan/127.0.0.1/1/10')
    assert resp.status == 200
    data = await resp.json()
    assert type(data['data']) is list
    assert len(data['data']) == 10

# _________________________ pytest _____________________________________


logger = logging.getLogger('aiohttp.access')
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler())

if __name__ == '__main__':
    print('Starting!')
    web.run_app(get_app(), host='127.0.0.1', port=8080)
验证说明

修复后启动服务,访问http://127.0.0.1:8080/scan/127.0.0.1/1/10即可正常返回JSON格式的端口扫描结果,不会再抛出500错误,pytest测试用例也可正常跑通。


内容的提问来源于stack exchange,提问作者Parcurcik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:36:22