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

Python for循环处理抛异常迭代器:记录异常后继续迭代的方法

问题核心说明

你遇到的UnicodeDecodeError并非csv.reader迭代逻辑抛出,而是底层标准输入流在做字节到文本解码时触发。如果直接在遍历reader的循环里加异常捕获,无法实现「记录异常后继续迭代」的效果:解码异常抛出时,默认文本流的迭代器已经进入无效状态,后续继续迭代会出现数据错乱、丢内容甚至再次抛错的问题。

Pythonic 实现方案

核心思路是接管流的解码逻辑,不要依赖默认的严格解码模式,从根源上避免解码异常打断整个迭代流程,根据需求可以选两种实现:


方案1:自定义解码错误处理(推荐,不丢失行内容)

通过标准库codecs模块注册自定义的解码错误回调,遇到坏字节时自动记录日志,用Unicode替换字符填充坏位置后继续解码,完全不打断csv的正常解析流程:

import csv
import sys
import logging
import codecs

logging.basicConfig(level=logging.WARNING)
csv.field_size_limit(10_000_000)

# 解码异常回调:记录日志后返回替换字符,指定后续解码位置
def decode_error_handler(exc: UnicodeDecodeError):
    logging.warning(
        f"解码异常,字节位置{exc.start}-{exc.end},原因:{exc.reason},坏字节将替换为\ufffd"
    )
    return ("\ufffd", exc.end)

# 注册自定义错误处理规则
codecs.register_error("log_and_replace", decode_error_handler)

# 从二进制缓冲区重新包装带容错能力的文本流
stdin_wrapper = codecs.getreader("utf-8")(sys.stdin.buffer, errors="log_and_replace")
reader = csv.reader(stdin_wrapper)

for row in reader:
    # 正常业务处理逻辑
    pass

这个方案完全复用标准库csv的解析能力,不需要自己处理行拆分、引号嵌套等边界情况,坏行的其余正常内容可以保留,后续只要检查行内是否存在\ufffd字符就能定位损坏的行。


方案2:逐行二进制读取(适合整行跳过场景)

如果你不需要保留损坏行的内容,只要遇到解码错误就跳过整行,可以直接从二进制缓冲区逐行读取,单独给每一行做解码:

import csv
import sys
import logging

logging.basicConfig(level=logging.WARNING)
csv.field_size_limit(10_000_000)

for line_no, raw_line in enumerate(sys.stdin.buffer, start=1):
    try:
        text_line = raw_line.decode("utf-8")
    except UnicodeDecodeError as e:
        logging.warning(f"第{line_no}行解码失败,已跳过,原因:{e.reason}")
        continue
    # 解码成功的行交给csv解析
    for row in csv.reader([text_line]):
        # 正常业务处理逻辑
        pass

这个方案逻辑更直观,但如果csv内容里存在带换行符的引号包裹字段,逐二进制行拆分可能破坏字段结构,兼容性弱于第一种方案。


避坑提示

不要直接在原遍历循环外层套try-except后强行继续迭代,默认文本流抛出解码异常后,内部读指针的状态不可控,继续读取会出现内容错乱、数据丢失的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:09:41