使用 error_bad_lines=False(pandas 1.3+ 已弃用)会直接跳过错误行,但需警惕数据丢失;旧版 pandas 中该参数用于处理解析异常。

使用 error_bad_lines=False(pandas 1.3+ 已弃用)会直接跳过错误行,但要小心数据丢失
旧版 pandas(pd.read_csv(..., error_bad_lines=False) 能静默跳过解析失败的行,比如字段数不匹配、引号不闭合等。但该参数在 1.3 版本后被移除,强行使用会报 TypeError: read_csv() got an unexpected keyword argument 'error_bad_lines'。
替代方案是改用 on_bad_lines='skip'(pandas ≥ 1.3),它行为一致但更明确:
import pandas as pd
df = pd.read_csv("data.csv", on_bad_lines='skip')
- 只跳过整行解析失败的记录,不修复、不填充
- 不会警告,容易掩盖数据质量问题——比如某列本该是数字,却因格式错乱被整行丢弃
- 适用于预处理阶段快速获得可用子集,但不适合审计或 ETL 场景
用 on_bad_lines='warn' 看清哪几行坏了,再决定怎么处理
比直接跳过更稳妥的做法是先暴露问题:on_bad_lines='warn' 会在控制台打印警告,并附带出错行号和原始内容片段:
df = pd.read_csv("data.csv", on_bad_lines='warn')
常见触发场景包括:
- CSV 行中逗号出现在未加引号的文本里(如
"Smith, John",25正确;Smith, John,25错误) - 换行符嵌在双引号内但解析器未启用
lineterminator或quoting - 编码不匹配导致某行字节流截断,引发字段数计算错误
这时你可以配合 error_handler 自定义逻辑(见下一条),而不是靠肉眼翻警告。
自定义错误处理器:用 on_bad_lines=lambda x: ... 拦截并结构化坏行
pandas 1.4+ 支持传入函数给 on_bad_lines,接收一个 ParserError 对象,从中提取原始行内容和行号:
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
def handle_bad_line(err):
print(f"Bad line {err.line_num}: {repr(err.args[0][:100])}")
# 返回 None 表示跳过;返回 list 表示用该 list 替代原行(需长度匹配列数)
return None
<p>df = pd.read_csv("data.csv", on_bad_lines=handle_bad_line)</p>
- 必须返回
None或与列数一致的list,否则抛ValueError - 适合做日志归档:把
err.line_num和err.args[0]写进单独的bad_lines.log - 不能修改原始 CSV 文件,仅影响内存中的 DataFrame 构建过程
底层更可控:用 csv 模块逐行 try/except,适合清洗逻辑复杂或需保留原始字符串的场景
当 pandas 的跳过/警告机制不够用(例如需要按列修复缺失值、识别半结构化字段、或兼容非标准分隔符),直接上 Python 标准库更透明:
import csv
<p>rows = []
with open("data.csv", encoding="utf-8") as f:
reader = csv.reader(f)
for i, row in enumerate(reader, 1):
try:</p><h1>假设已知应有 4 列,补空或截断</h1><pre class="brush:php;toolbar:false;"> if len(row) 4:
row = row[:4]
rows.append(row)
except Exception as e:
print(f"Row {i} failed: {e}, raw={row}")
- 完全绕过 pandas 解析器,不受
quoting、escapechar等参数限制 - 每行都是
list[str],没有类型自动推断——你要自己调int()或float() - 性能略低,但对“脏数据多、规则杂”的小到中型文件更可靠
真正麻烦的不是跳过坏行,而是搞不清坏在哪一环:是编码?引号?嵌套换行?还是 Excel 导出时的非标准转义?先用 on_bad_lines='warn' 定位,再选策略,比一开始就写 try/except 更省力。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










