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

Python中程序某部分等待时如何执行其他操作

OpenWeatherMap API限流场景下利用等待时间处理入库任务的实现方案

核心思路是避免用同步阻塞等待浪费CPU时间,将API请求和数据入库两类IO任务解耦,在限流冷却窗口期调度执行入库任务,最大化资源利用率。

推荐方案1:生产者消费者线程模型(易维护,兼容性好)

适合中小规模请求量,代码逻辑简单易调试,不需要引入异步生态依赖。

  • 初始化两个队列分别存储待请求的位置参数、待入库的天气数据
  • 单独启动API请求线程,严格按照每分钟60次的速率发起请求,每满60次后进入冷却期:
    • 冷却期内优先消费待入库队列的数据执行数据库写入操作
    • 冷却时间到后重置请求计数,恢复API请求
  • 若待入库数据量较大,可额外启动多个入库线程并行消费,API请求线程的冷却期也可参与消费,进一步提升处理速度

简化示例代码

import time
import threading
from queue import Queue
import requests

# 基础配置
OPENWEATHER_API_KEY = "替换为你的API密钥"
MAX_REQUESTS_PER_MINUTE = 60
RATE_LIMIT_WINDOW_SEC = 60

# 队列初始化
pending_request_queue = Queue()
pending_save_queue = Queue()

# 示例:将所有待查询的城市ID写入请求队列
for city_id in [12345, 23456, 34567]:  # 替换为你的实际待查询列表
    pending_request_queue.put(city_id)

def api_request_worker():
    request_counter = 0
    window_start_time = time.time()
    while not pending_request_queue.empty():
        # 触发热限流判断
        if request_counter >= MAX_REQUESTS_PER_MINUTE:
            elapsed_sec = time.time() - window_start_time
            # 未到冷却结束时间则处理入库任务
            while elapsed_sec < RATE_LIMIT_WINDOW_SEC:
                if not pending_save_queue.empty():
                    weather_data = pending_save_queue.get()
                    # 替换为你的实际数据库写入逻辑
                    # db_connection.insert("weather_table", weather_data)
                    pending_save_queue.task_done()
                else:
                    # 无待入库任务时短休眠避免空转消耗CPU
                    time.sleep(0.2)
                elapsed_sec = time.time() - window_start_time
            # 冷却结束重置计数和时间窗口
            request_counter = 0
            window_start_time = time.time()
        # 发起API请求
        current_city_id = pending_request_queue.get()
        resp = requests.get(
            url="https://api.openweathermap.org/data/2.5/weather",
            params={"id": current_city_id, "appid": OPENWEATHER_API_KEY}
        )
        resp.raise_for_status()
        pending_save_queue.put(resp.json())
        request_counter += 1
        pending_request_queue.task_done()

if __name__ == "__main__":
    # 启动API请求线程
    threading.Thread(target=api_request_worker, daemon=True).start()
    # 等待所有请求和入库任务完成
    pending_request_queue.join()
    pending_save_queue.join()

推荐方案2:异步IO模型(高性能,适合大规模请求)

如果请求量在数千以上,推荐用asyncio生态实现,单线程即可处理大量IO任务,上下文切换开销远低于多线程方案。

  • 用aiohttp发送异步API请求,用异步数据库驱动(如aiomysql、asyncpg)执行入库操作
  • 用令牌桶算法控制API请求速率,令牌耗尽时调度执行待入库的异步任务

注意事项

  • 建议添加请求重试逻辑,处理偶发的429限流、5xx服务错误,可通过tenacity库快速实现重试装饰器
  • 数据库写入建议批量提交,比如每攒够20~50条数据再一次性写入,可大幅降低IO开销
  • 若多实例分布式部署,需将总限流配额拆分到每个实例,避免整体超过平台限流阈值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 10:39:03