clevercsv,一个有趣的 Python 库!
有些 CSV 文件,长得像 CSV,读起来根本不像。
你拿 csv.DictReader 一把梭,跑得好好的。第二天换了个供应商导出的文件,分隔符从逗号变成分号,字段里还夹着一堆没转义干净的引号,结果脚本不是读错列,就是整行糊掉。更烦的是,这种文件你肉眼看着“也还行”,程序一吃就炸。
这类脏活我一般不先怪业务代码,先怀疑文件本身。尤其是 CSV 这种格式,表面最朴素,实际最容易藏坑。clevercsv 这个库,就挺适合干这个事。它不是什么大而全的数据处理框架,干的事情很专一:尽量把那些“不太标准但现实里经常遇到”的 CSV 文件,给你猜对、读出来。 这种切入和落法,和我平时写技术文时强调的“先落现场、再落判断”的手感是一致的。
先看个很常见的现场文件:
sample = """order_id;user_name;remark
1001;alice;"paid, wait deliver"
1002;bob;"need ""red"" invoice"
"""
这玩意如果你默认按逗号读,第二列第三列就直接串了。标准库当然也能处理,但前提是你得先知道分隔符、quotechar、escape 这些细节。问题就在这儿:线上接文件时,你往往并不知道。
clevercsv 的用法不复杂,先让它猜 dialect,再按猜出来的规则读。
import clevercsvwith open("orders.csv", "r", encoding="utf-8") as f:
data = f.read()
dialect = clevercsv.Sniffer().sniff(data)
print(dialect.delimiter) # 可能是 ; 或 ,
print(dialect.quotechar) # 可能是 " 或其他
rows = clevercsv.read_table("orders.csv")
for row in rows[:3]:
print(row)
这地方我第一眼就比较信它的点,不是“自动识别”这四个字,而是它专门在 CSV dialect 检测这件事上做了不少针对性处理。现实里的问题从来不是“不会读 CSV”,而是“文件格式不老实”。clevercsv 干的就是这个脏活。
平时如果你只接自己系统导出的文件,其实没必要上它。规规矩矩的逗号分隔、双引号转义、UTF-8 编码,标准库够了:
import csvwith open("orders.csv", newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["order_id"], row["user_name"])
但只要文件来源一杂,事情马上就不是这么回事了。比如财务导出来的文件爱用分号,欧洲区系统导出来的小数点和分隔符还经常互相打架,某些老系统甚至会把一列里的换行也混进去。你这时候再指望人工先打开文件看一眼,再改脚本,基本等于放弃自动化。
我之前写过一个批量导入脚本,目录里每天会丢进来几十个 CSV,来源不统一。最开始偷懒,直接 pandas.read_csv(),参数靠试。后来发现错一批数据,比直接报错还难受。因为报错至少知道停了,读错列是真会往库里灌脏数据。
后来我就把入口换成了“先识别,再校验”这一套:
import clevercsv
from pathlib import Pathdefload_csv_safely(file_path: str):
text = Path(file_path).read_text(encoding="utf-8", errors="replace")
dialect = clevercsv.Sniffer().sniff(text)
rows = clevercsv.read_table(file_path)
header = rows[0] if rows else []
if"order_id"notin header:
raise ValueError(f"{file_path} 表头不对, dialect={dialect}")
return rows
files = Path("./incoming").glob("*.csv")
for f in files:
try:
rows = load_csv_safely(str(f))
print(f"{f.name} OK, {len(rows)} rows")
except Exception as e:
print(f"{f.name} FAIL: {e}")
这段代码不花哨,但很像线上会留着的东西:先把文件吃进来,识别规则,再做最基本的表头兜底。因为很多时候,能读出来不代表读对了。这一点比库本身更重要。
再说个容易忽略的点:clevercsv 解决的是 CSV 结构识别,不是万能数据清洗。比如编码乱掉、列名写错、字段缺失、金额列混进中文备注,这些事它不管。别把工具用大了。它适合放在“导入链路的前半段”,帮你把文件先按比较靠谱的方式切开,后面再接自己的业务校验。
比如金额字段,你还是得自己兜:
defnormalize_amount(raw: str) -> float:
value = raw.strip().replace(",", "")
return float(value) if value else0.0
很多人一提这种库,就容易写成“提高效率、增强兼容性、适用于多场景”。这种话不能说错,但没什么用。真正有感觉的地方是:你碰到一批野路子 CSV,不想每次手改参数,不想把导入脚本写成猜谜游戏,这时候 clevercsv 能帮你少踩不少坑。
安装也很直接:
pip install clevercsv
然后记住一个判断就够了:
你控制文件格式,用标准库; 你不控制文件来源,先试 clevercsv。
它不算什么重量级神器,但挺有工程味。不是为了炫技,是为了少被脏数据折腾。很多库有趣,不是因为概念新,而是因为它刚好补在那个你反复骂人的位置上。
clevercsv 就属于这一类。