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

如何在df.apply()函数抛出异常时获取已计算的部分结果?

不用必须改用for循环,但逐行迭代是更可靠的方案

当你用df.apply()处理这类耗时且可能出错的API调用时,确实会遇到「中途异常/中断就丢失所有已计算结果」的问题——因为apply()是先完成所有行的计算、生成完整的Series后才会赋值给DataFrame列,中途一旦抛出异常或被中断,之前的计算结果根本没机会写入原DataFrame。

你不一定必须改用for循环,但逐行迭代(比如for循环)是最直接、可控性最强的方案,能实时保存已完成的结果。下面是优化后的代码示例:

import random
import time 
import pandas as pd

# 模拟慢速且可能抛出异常的REST API
def getApiValue_sim(p1:int, p2:int) -> int:
    time.sleep(1) # 模拟请求耗时
    i = random.randint(p1,p2)
    if not i%4:
        raise Exception("Multiple of 4")
    return i

dataframe = pd.DataFrame({'P1':[1,2,3],'P2':[11, 12, 13],'Reply':[pd.NA,pd.NA,pd.NA]})

try:
    # 逐行迭代处理,只更新未填充的行
    for idx, row in dataframe.iterrows():
        if pd.isna(row['Reply']):
            try:
                # 实时写入结果到DataFrame
                dataframe.loc[idx, 'Reply'] = getApiValue_sim(row['P1'], row['P2'])
            except Exception as e:
                # 捕获单条请求的异常,不终止整个流程
                print(f"行{idx}处理失败: {str(e)}")
                # 可选:添加错误列记录失败原因
                dataframe.loc[idx, 'Error'] = str(e)
except KeyboardInterrupt:
    # 处理用户CTRL-C中断的情况
    print("程序被用户手动中断")
finally:
    # 无论异常/中断,都输出并保存已完成的结果
    print("已完成的结果:")
    print(dataframe)
    # 保存到文件,避免数据丢失
    dataframe.to_csv('partial_result.csv', index=False)

这个方案的优势:

  • 实时更新DataFrame,中途任何异常或中断都不会丢失已处理完的行数据
  • 单条请求失败不会阻断整个流程,还能记录错误信息
  • 可以跳过已填充的行,方便脚本中断后重启继续处理

如果坚持想用apply(),也可以在每行的处理函数里捕获异常,但这种方式无法解决「CTRL-C中断丢失结果」的问题——因为apply()要等所有行计算完成才会赋值。示例代码如下:

try:
    def process_row(row):
        if pd.isna(row['Reply']):
            try:
                return getApiValue_sim(row['P1'], row['P2'])
            except Exception as e:
                print(f"行{row.name}处理失败: {str(e)}")
                return pd.NA
        return row['Reply']
    
    # 只有当所有行计算完成后,才会赋值给Reply列
    dataframe['Reply'] = dataframe.apply(process_row, axis=1)
except KeyboardInterrupt:
    print("程序被中断")
finally:
    print(dataframe)

但要注意:如果中途被CTRL-C中断,apply()还没生成完整的结果Series,原DataFrame的Reply列还是初始的全缺失值,之前计算的所有结果都会丢失。

综上,如果你需要确保异常或中断时保留已完成的结果,优先选择逐行迭代的for循环方案。


内容的提问来源于stack exchange,提问作者Maxime Charrière

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:45:58