Python中如何在带计数器的for循环内调度API调用
实现逻辑问题排查
你当前写的暂停逻辑有3个致命问题,运行后完全达不到预期效果:
- 计数统计不准确:
count累加放在了返回值非空的判断分支里,API返回None(比如请求失败、目标数据为空)的场景不会被计数,实际调用次数达到450次的限流阈值时,程序不会触发暂停。 schedule库使用逻辑错误:- 触发阈值时你注册了每小时递归调用
master_function()的定时任务,之后进入死循环跑调度,会导致整个函数从头开始重复执行,之前已经拉取的数据、计数状态全部重置,最终出现重复拉取、内存溢出、无限递归的问题。 - 这个死循环没有退出条件,就算1小时后任务执行完成,程序也永远跳不出循环,不会继续处理剩余的测试项。
- 触发阈值时你注册了每小时递归调用
- 计数器没有重置逻辑:就算勉强实现了暂停,恢复执行后
count的值仍然是450,下一次循环会立刻再次触发暂停,程序会卡在反复等待的状态无法继续。
正确实现方式
不需要引入schedule做定时任务,直接用标准库的time.sleep()就能满足需求,核心调整点:
- 把计数器累加移动到API调用语句之后,只要发起了API请求就计数,完全匹配限流统计规则。
- 触发450次阈值时直接休眠3600秒(即1小时),休眠结束后把计数器重置为0,继续循环处理后续数据即可。
- 删除递归调用主函数、死循环跑调度的错误逻辑。
- 把原代码里的变量名
id改成test_id,避免覆盖Python内置的id()函数引发异常。
修正后的完整可运行代码如下:
import time import pandas as pd # 其余原有依赖导入保持不变 def master_function(): test_data = sev_one_api_calls.get_all_catchpoint_tests() flat_getAll = pd.DataFrame([flatten_json(test_data[key]) for key in test_data]) call_count = 0 concat_data = pd.DataFrame() for test_name, test_details in test_data.items(): test_id = test_details.get('id') print(test_name, test_id) # 发起API请求后直接计数,不管返回结果是否为空 test_detailed_data = sev_one_api_calls.get_catchpoint_test_detail(test_id) call_count += 1 if test_detailed_data is not None: flat_detailed_data = json_to_dataframe(test_detailed_data) concat_data = pd.concat([concat_data, flat_detailed_data], ignore_index=True) # 达到阈值时暂停1小时,重置计数器 if call_count >= 450: print(f"累计API调用达到450次,暂停1小时,暂停开始时间:{time.ctime()}") time.sleep(3600) call_count = 0 print(f"暂停结束,恢复执行,恢复时间:{time.ctime()}") # 后续数据合并、导出逻辑保持原有逻辑不变 combined = pd.merge(flat_getAll, concat_data, on='id', how='outer', left_index=True, right_index=True, suffixes=('', '_remove')) combined.drop([i for i in combined.columns if 'remove' in i], axis=1, inplace=True) df = combined.groupby('id', as_index=False).first() df.to_csv('../../data/COMBO.csv', index=False)
可选优化点
- 循环内反复用
pd.concat拼接DataFrame的效率极低,数据量大时运行速度会非常慢,可以先把所有拉取到的明细数据存在Python列表里,等整个循环结束后一次性转成DataFrame,性能会有明显提升。 - 建议给API调用加try-except异常捕获和有限次重试逻辑,避免单次网络波动、请求失败导致整个任务中断。
- 如果对接的API限流规则是自然小时窗口(比如每自然小时最多允许450次请求,而非每打满450次硬等1小时),可以记录窗口内第一次请求的时间戳,到阈值时计算当前窗口剩余等待时间即可,不需要每次都等满1小时,能大幅缩短整体任务耗时。
内容的提问来源于stack exchange,提问作者Rebekah Lee
相关产品推荐
相关产品推荐

