排查difflib因字符串差异过大导致的报错及定位问题行
定位difflib报错的具体数据行方法
针对你处理1100万行文本数据时触发的difflib报错,以下是几个实用的定位方案:
1. 给diff函数添加异常捕获(直接定位出错行)
修改你的diff函数,加入try-except块,捕获所有异常并打印出错的行索引和对应文本内容,报错时就能直接拿到具体问题行:
from difflib import ndiff import pandas as pd from tqdm import tqdm tqdm.pandas() dat = pd.read_csv("all_ks_dat_good.csv", delimiter="|", encoding="ISO-8859-1") def diff(x): try: s1 = str(x['last_text']) s2 = str(x['scrubbed_text']) l = [c[-1] for c in ndiff(s1, s2) if c[0] == '+'] return ''.join(l) except Exception as e: # 打印关键信息,方便定位 print(f"出错行索引: {x.name}") print(f"last_text内容: {repr(s1)}") # repr能显示转义字符 print(f"scrubbed_text内容: {repr(s2)}") print(f"错误详情: {str(e)}") # 返回标记值,不中断整体进程 return "ERROR" dat['add_ks'] = dat.progress_apply(diff, axis=1)
运行后,一旦触发报错,控制台会直接输出出错行的索引和对应文本,精准定位问题数据。
2. 分批测试缩小范围
如果异常捕获暂时没生效,或者想快速锁定出错区间,可以分批加载数据测试:
- 先取前1万行:
dat_small = dat.head(10000),运行代码看是否报错 - 若报错,拆分前5000行、后5000行逐步缩小范围;若不报错,扩大到10万行、50万行,直到找到出错批次
- 找到批次后,用二分法进一步定位具体行
3. 预处理排查异常文本
从报错栈看,问题出在SequenceMatcher处理字符串时,大概率是文本包含特殊控制字符(比如\x00空字符、不可见转义符)或超长字符串导致的。可以先排查这两列的异常值:
# 检查文本长度,找出超长行 dat['last_len'] = dat['last_text'].apply(lambda x: len(str(x))) dat['scrub_len'] = dat['scrubbed_text'].apply(lambda x: len(str(x))) # 筛选长度超过阈值的行(比如10000字符) print(dat[dat['last_len'] > 10000][['last_len', 'last_text']]) print(dat[dat['scrub_len'] > 10000][['scrub_len', 'scrubbed_text']]) # 检查是否包含控制字符 import re control_char_re = re.compile(r'[\x00-\x1f\x7f-\x9f]') dat['last_has_control'] = dat['last_text'].apply(lambda x: bool(control_char_re.search(str(x)))) dat['scrub_has_control'] = dat['scrubbed_text'].apply(lambda x: bool(control_char_re.search(str(x)))) # 筛选含控制字符的行 print(dat[dat['last_has_control']][['last_text']]) print(dat[dat['scrub_has_control']][['scrubbed_text']])
这些预处理能帮你提前找出可能引发错误的异常文本,直接定位问题行。
内容的提问来源于stack exchange,提问作者Adam_G
相关产品推荐
相关产品推荐

