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

Python Asyncio多无限循环异步函数出错时周期延迟问题咨询

问题分析与解决方案

核心原因

你遇到的延迟问题,本质是get_exchange_rate()里用的requests是同步阻塞库。当触发SSLError并自动重试时,整个asyncio事件循环会被这个同步阻塞操作卡住——因为asyncio是单线程模型,一旦某个任务占用了线程,其他任务(比如每5秒执行的data_input())就只能等待,直到阻塞操作结束,自然就出现了延迟。

解决方法

1. 改用异步HTTP库(推荐)

把同步的requests换成异步HTTP库(比如aiohttp),让网络请求变成非阻塞操作,不会卡住事件循环。

示例代码:

import aiohttp
import asyncio
from bs4 import BeautifulSoup

async def get_exchange_rate():
    while True:
        try:
            async with aiohttp.ClientSession() as session:
                async with session.get("目标URL") as resp:
                    resp.raise_for_status()
                    html = await resp.text()
                    soup = BeautifulSoup(html, "html.parser")
                    # 处理汇率解析逻辑
        except aiohttp.ClientError as e:
            print(f"请求出错: {e}")
        await asyncio.sleep(30)

async def data_input():
    while True:
        # 数据保存逻辑
        print("执行数据保存")
        await asyncio.sleep(5)

async def main():
    await asyncio.gather(
        get_exchange_rate(),
        data_input(),
        return_exceptions=True
    )

if __name__ == "__main__":
    asyncio.run(main())

2. 给同步请求套线程池(兼容现有代码)

如果不想替换requests,可以用asyncio.to_thread()(Python 3.9+)或者loop.run_in_executor()把同步的requests操作放到线程池执行,避免阻塞事件循环。

示例代码:

import requests
import asyncio
from bs4 import BeautifulSoup

async def get_exchange_rate():
    while True:
        try:
            # 把同步请求放到线程池执行
            response = await asyncio.to_thread(requests.get, "目标URL")
            response.raise_for_status()
            soup = BeautifulSoup(response.text, "html.parser")
            # 处理汇率解析逻辑
        except requests.exceptions.SSLError as e:
            print(f"SSL错误: {e}")
        await asyncio.sleep(30)

async def data_input():
    while True:
        print("执行数据保存")
        await asyncio.sleep(5)

async def main():
    await asyncio.gather(
        get_exchange_rate(),
        data_input(),
        return_exceptions=True
    )

if __name__ == "__main__":
    asyncio.run(main())

3. 优化错误重试逻辑

不管用哪种方式,都要在get_exchange_rate()里明确捕获SSLError,避免无限制的自动重试(requests默认重试可能耗时很久),同时控制重试的间隔,减少对事件循环的影响。

比如在捕获错误后,直接进入下一个30秒周期:

async def get_exchange_rate():
    while True:
        try:
            # 请求逻辑
        except requests.exceptions.SSLError as e:
            print(f"SSL错误,跳过本次请求: {e}")
        # 不管成功失败,都等待30秒再执行下一次
        await asyncio.sleep(30)

内容的提问来源于stack exchange,提问作者윤태일

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:25:16