SKU表导出后,用 csv 保住前导零和逗号要处理的不是商品效果,而是一类可以由程序明确判断的输入问题。CSV中SKU始终按字符串处理,使用DictReader与DictWriter保留前导零,并让带逗号的商品名按标准引用规则往返。必填列缺失和重复SKU明确拒绝。
SKU表导出后,用 csv 保住前导零和逗号要处理的不是商品效果,而是一类可以由程序明确判断的输入问题。CSV中SKU始终按字符串处理,使用DictReader与DictWriter保留前导零,并让带逗号的商品名按标准引用规则往返。必填列缺失和重复SKU明确拒绝。
输入契约与实现
CSV中SKU始终按字符串处理,使用DictReader与DictWriter保留前导零,并让带逗号的商品名按标准引用规则往返。必填列缺失和重复SKU明确拒绝。

代码把CSV字符串往返限定成小范围任务,刻意不增加网络请求、文件覆盖和发布动作。
运行结果与排错
001保持前导零,带逗号名称完整保留,输出再读与原行相同;重复SKU抛出blank_or_duplicate_sku。
如果电子表格导出前已经把001改成1,代码无法恢复丢失的信息。导出时应设置文本字段,本例只验证拿到的CSV字符串。如果要扩大范围,先添加对应失败夹具,再修改实现。
成功分支同样要验证结果含义。
放在图片制作链路的哪里
这个工具适合放在CSV保真工具相关的本地资料整理环节,和图像制作保持解耦。
实际交接至少保留输入版本、代码版本和完整报告。
本例的覆盖范围是:001保持前导零,带逗号名称完整保留,输出再读与原行相同;重复SKU抛出blank_or_duplicate_sku。未覆盖的边界是:如果电子表格导出前已经把001改成1,代码无法恢复丢失的信息。导出时应设置文本字段,本例只验证拿到的CSV字符串。
import csv, io, json
def roundtrip(text):
reader = csv.DictReader(io.StringIO(text, newline=''))
if not {'sku', 'name'} <= set(reader.fieldnames or []):
raise ValueError('missing_columns')
rows, seen = [], set()
for row in reader:
sku = row['sku']
if not sku or sku in seen:
raise ValueError('blank_or_duplicate_sku')
if row['name'] is None:
raise ValueError('missing_name')
seen.add(sku)
rows.append({'sku': sku, 'name': row['name']})
output = io.StringIO(newline='')
writer = csv.DictWriter(output, fieldnames=['sku', 'name'], lineterminator='\n')
writer.writeheader()
writer.writerows(rows)
return output.getvalue(), rows
text = 'sku,name\n001,"杯子,带盖"\n002,托盘\n'
encoded, rows = roundtrip(text)
assert rows[0] == {'sku': '001', 'name': '杯子,带盖'}
assert roundtrip(encoded)[1] == rows
try:
roundtrip('sku,name\n001,杯子\n001,托盘\n')
except ValueError as exc:
assert str(exc) == 'blank_or_duplicate_sku'
else:
raise AssertionError('expected rejection')
print(json.dumps({'rows': rows, 'error': 'blank_or_duplicate_sku'}, ensure_ascii=False))
编辑复核与下一组测试
CSV保真应看读入后的字段值和再次读回的结果,不应只看输出文件在文本编辑器里是否排得整齐。本文以001保持前导零、带逗号商品名完整保留、输出再读与原行相同作为成功对照,说明DictReader与DictWriter处理的是字段边界和字符串内容。商品名中的逗号属于值的一部分,不能用简单按逗号切分来核对列数;输出时出现引用符号是CSV表达该字段的方式,不是给商品名新增了要展示的引号。SKU也不应在检查后转换成整数,否则001和1会失去原本不同的标识。重复SKU抛出blank_or_duplicate_sku时,接收者应回看SKU列,先分辨是空白身份还是同一身份出现多次,再检查对应商品名和来源行;不能因为后两行名称不同就保留相同SKU,也不能把重复项全部删去而不确定哪条才是应交付记录。必填列缺失属于表头与契约不一致,应先确认导出选列或字段名称,不要逐行补值来掩盖列根本不存在的问题。下一组测试可让001与1同时出现,确认读取后保持两个不同字符串;再让同一个001出现两次,单独覆盖重复拒绝,与空SKU样例分开观察。对于商品名,可增加含双引号、逗号与换行的字段,通过写出再读回核对值,验证CSV引用规则没有被额外的字符串拼接破坏。还可以把必填列缺失与必填列存在但某行值为空做成对照,帮助维护者区分表级结构问题和记录级内容问题。若表格软件在导出之前已经把001变成1,本工具读到的就是1,往返一致也只能证明这个已经变化的值被保留,不能恢复丢失的零。发现这种情况应回到原始资料或导出设置确认文本格式,不能按统一长度补零,因为不同SKU的合法长度未必相同。这个环节应放在表格导出完成、SKU清单交给图片映射之前,让后续流程拿到稳定的身份和完整商品名。交接时可提供读取结果与回读核对结论,而不是要求接收者凭电子表格的显示外观判断保真;如果对方再次打开、编辑并导出文件,还应在那个新节点重新核对字符串。这样才能把CSV工具负责的往返保留,与上游已发生的类型转换损失清楚分开。