csv.reader 遇损坏行默认抛 csv.error 中断迭代,需用 try/except 包裹单行解析以跳过坏行;pandas.read_csv 用 on_bad_lines="skip" 可跳过异常行,配合 encoding_errors="ignore" 和 nullable dtype 更健壮;数据库插入应避免大事务,改用 insert ignore 或分批提交并捕获 integrityerror。
csv.reader 遇到损坏行直接抛异常?用 try/except 包裹单行解析
python 默认的 csv.reader 在遇到格式严重错误(比如引号不匹配、换行符嵌在字段里没转义)时会抛 csv.error,整个迭代中断。这不是 bug,是设计使然——它假设输入是合规 csv。
要跳过坏行继续,必须把每行解析逻辑单独包进异常处理里:
import csv
<p>with open("data.csv") as f:
reader = csv.reader(f)
for i, row in enumerate(reader, 1):
try:</p><h1>假设你后续要插入数据库,这里做类型转换或校验</h1><pre class="brush:php;toolbar:false;"> user_id = int(row[0])
email = row[1].strip()
# ... 其他字段处理
insert_into_db(user_id, email)
except (ValueError, IndexError, csv.Error) as e:
print(f"跳过第 {i} 行:{row!r} — {e}")
continue
-
csv.Error捕获底层解析失败(如 unclosed quote) -
ValueError和IndexError覆盖常见业务层错误(字段缺失、类型不对) - 别在
except里吞掉所有异常(比如Exception),否则磁盘 IO 错误或内存问题也会被静默忽略
pandas.read_csv 的 on_bad_lines 参数怎么选
如果你用 pandas 加载再入库,on_bad_lines 是关键开关。它不是“跳过就完事”,不同取值行为差异很大:
-
on_bad_lines="skip":跳过整行,但要求文件本身是合法 UTF-8 且无嵌入换行;遇到二进制乱码或 \x00 字节仍会报UnicodeDecodeError -
on_bad_lines="warn":打印警告并跳过,适合调试阶段定位坏行位置 -
on_bad_lines="error"(默认):遇到任何解析异常立刻中断 - 注意:
on_bad_lines在 pandas ≥ 1.3.0 才支持;旧版本只能靠error_bad_lines=False(已弃用)或预处理文件
实操建议:
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
import pandas as pd
<p>df = pd.read_csv(
"data.csv",
on_bad_lines="skip",
encoding_errors="ignore", # 额外加这行,跳过非法字节(比如 Windows 记事本存的 GBK 混入 UTF-8 文件)
dtype={"id": "Int64"} # 用 nullable int 类型,避免空字符串转 int 报错
)</p>
数据库插入时如何避免因单行失败导致事务整体回滚
即使 CSV 解析成功,INSERT 还可能因唯一约束、字段超长、NULL 不允许等失败。如果用一个大事务包全部插入,一行出错就全滚,反而丢失更多有效数据。
- 对 MySQL/PostgreSQL:用
INSERT IGNORE或ON CONFLICT DO NOTHING替代普通INSERT,让数据库层面跳过冲突行 - 对 SQLite:支持
INSERT OR IGNORE,但要注意它只忽略约束冲突,不处理类型转换错误 - 更稳妥的做法是每行一个独立事务(或批量 commit,比如每 100 行 commit 一次),并在 Python 层捕获
IntegrityError等数据库异常 - 别依赖
autocommit=True,它会让 DDL 语句也自动提交,容易引发意外状态
损坏行经常藏在哪儿?提前筛比事后补救更省力
很多“损坏”其实有规律可循,与其在导入时硬扛,不如前置过滤:
- 用
file命令看编码:file -i data.csv,如果是iso-8859-1却当 UTF-8 读,必然在某个非 ASCII 字符处崩 - 用
head -n 100 data.csv | cat -A查看隐藏字符,^M(CRLF)、$(行尾)、^@(空字节)都是常见元凶 - Excel 导出的 CSV 经常在最后一行多一个空行,或第一行列名含 BOM;用
open(..., encoding="utf-8-sig")自动剥离 BOM - 如果源是用户上传,强制在前端加校验(如限制文件大小、检查 MIME type),后端别信
Content-Type字段
真正难搞的是那些看似正常、但某字段里混了未转义的双引号 + 换行组合,这种必须靠 csv 模块的真实解析才能暴露——所以日志里留好原始行内容和行号,比什么都重要。










