SKU图片在不同系统之间交接,文件名可能出现隐藏冲突:A.png与a.png在一些环境中可并存,换到另一个环境却可能覆盖;看起来一样的带重音字符,也可能采用不同Unicode表示。上传前可以建立保守的比较键,找出风险分组。检查结果只提示可能冲突,不自动重命名,更不删除文件。
本例使用Python标准库unicodedata,把名称归一到NFC,再进行casefold比较。官方文档分别说明Unicode归一化和字符串大小写折叠。这个比较键是本次交接的检查策略,不等于每个文件系统的实际规则;它可能把某些可并存名称列入风险组,负责人仍需要结合目标系统决定怎样处置。
比较键与原始名称都要保留
输入是明确的文件名列表,函数返回每个键对应的原始名称组。原始名称不能被归一化后的键替代,因为查问题需要知道实际文件是哪一个。空名称和非字符串直接拒绝,避免把缺失字段转成一个普通文本参与比较。本例不扫描文件内容,不把名称相同或相近解释成图片内容重复。
import unicodedata
def collisions(names):
seen,groups={},[]
for name in names:
if not isinstance(name,str) or not name: raise ValueError(‘invalid filename’)
key=unicodedata.normalize(‘NFC’,name).casefold()
seen.setdefault(key,[]).append(name)
for values in seen.values():
if len(values)>1: groups.append(values)
return groups
函数只处理传入名称,没有网络和文件修改。项目如果按相对路径管理素材,应明确要比较整个路径还是同一目录下的末级名称;两种策略会得到不同结果。不能把不同目录中同名的图片自动归为错误,也不能遗漏同一路径的大小写差异。比较范围属于契约,应在调用前记录。
)2
assert collisions([‘A.png’,‘B.png’])[]
try:
collisions([‘’])
except ValueError:
print(‘empty filename refused’)
else:
raise AssertionError(‘expected rejection’)
测试分别提供大小写不同的名称,以及由组合字符形成的等价可见名称。预期得到两个风险组;另一组互不相同的名称应返回空列表。这个测试使用人工构造的文件名,验证的是比较逻辑,不声称已经扫描员工电脑或所有历史素材。实际目录仍要独立读取并保存本轮结果。
错误夹具提供空名称,函数应抛出异常。调用方记录这是一条输入契约问题,不要把它当成没有冲突。批量处理中,如果某行字段缺失,应先修订数据,再重新检查;偷偷过滤异常输入,可能让报告显得干净,却少检查了一部分任务。完整检查要能说明哪些记录没有进入比较。
发现冲突后先核对商品关联,再决定新名称。两个文件可能来自不同SKU,也可能是同一个文件的不同版本,处理方式不同。重命名会影响清单与页面引用,应该同步更新相关记录并保留旧新对应;本例不执行这个动作,避免没有依赖资料时擅自改变路径。
Picset官网展示SKU替换与商品图相关入口,图像生产可能产生需要交接的多规格素材。此脚本处在文件交接层,用来提示名称风险,不代表产品自带相同检测,也不评价其SKU功能效果。制作路径与文件管理是两件事,工具生成完成后,仍需让员工知道每个文件对应什么商品。
保守比较也有未覆盖处,例如平台保留名、路径长度、尾部空格或存储系统的其他限制。需要这些条件时另加针对目标系统的检查,不把NFC加casefold当作全部可上传规则。报告应记录当前策略与范围,员工才能知道空列表意味着没有命中本例规则,而非任何环境都不会冲突。
交接完成后再核对文件数量和实际内容,确认每个SKU的素材仍在。名称检查不替代商品核对,也不替代内容哈希校验。保留原始名称、比较键和处理记录,这个工具就能帮助团队提前发现跨系统风险,而不是在上传发生覆盖以后才凭印象找回少掉的图片。