Python subprocess调用ImageMagick星号通配符引发Unicode文件名异常
问题描述
我尝试在存放有其他图片文件的文件夹内创建文件名为Unicode字符*️⃣.png的文件。
该文件名的UTF-8编码为*\xef\xb8\x8f\xe2\x83\xa3.png,文件名中的星号在使用subprocess调用外部程序时出现异常,疑似被识别为glob规则中的通配符。
可通过以下代码复现该问题:
import subprocess from pathlib import Path ICON_CACHE_PATH = Path('/tmp') icon_path_9 = Path(ICON_CACHE_PATH / '9️⃣.png') icon_path_star = Path(ICON_CACHE_PATH / '*️⃣.png') subprocess.call([ 'convert', '-pointsize', '64', '-background', 'transparent', f'pango:{icon_path_9.stem}', icon_path_9 ]) subprocess.call([ 'convert', '-pointsize', '64', '-background', 'transparent', f'pango:{icon_path_star.stem}', icon_path_star ]) print(icon_path_star.exists())
运行上述代码后,并未正常生成分别对应两个Unicode字符图案的*️⃣.png和9️⃣.png文件,仅生成了内容包含星号的9️⃣.png文件,代码末尾的打印语句输出结果为False。
经排查该问题大概率为ImageMagick自身的处理逻辑问题:调用stat等其他二进制程序操作该文件名可正常运行。临时解决方案是先通过ImageMagick生成临时命名的文件,再使用Python将其重命名为目标文件名。
问题原因
该异常和Python的subprocess模块无关,也不是shell的glob展开导致的——即使不开启shell=True、使用参数列表形式传参,ImageMagick内部默认会对所有传入的文件路径做自主的通配符匹配,文件名开头的*刚好命中通配符规则,导致输出路径被错误解析,无法按字面量生成目标文件。
可行解决方案
不需要走临时文件重命名的绕路逻辑,两种原生方案即可直接修复:
- 针对单路径转义:在文件路径前添加
@:前缀,告诉ImageMagick该路径按字面量处理,不做任何通配符展开subprocess.call([ 'convert', '-pointsize', '64', '-background', 'transparent', f'pango:{icon_path_star.stem}', f'@:{icon_path_star}' ]) - 全局关闭通配符:调用
convert时添加-noglob参数,禁用本次执行全流程的glob展开逻辑subprocess.call([ 'convert', '-noglob', '-pointsize', '64', '-background', 'transparent', f'pango:{icon_path_star.stem}', icon_path_star ])
两种方案修改后都可以正常生成对应Unicode字符的*️⃣.png和9️⃣.png文件,路径存在性判断的打印结果也会正常返回True。
内容的提问来源于stack exchange,提问作者simonzack
相关产品推荐
相关产品推荐

