问题
你的程序获取了一个目录中的文件名列表,但是当它试着去打印文件名的时候
程序崩溃,出现了 UnicodeEncodeError 异常和一条奇怪的消息——surrogates notallowed 。
解决方案
当打印未知的文件名时,使用下面的方法可以避免这样的错误:
def bad_filename(filename):
return repr(filename)[1:-1]
try:
print(filename)
except UnicodeEncodeError:
print(bad_filename(filename))
讨论
这一小节讨论的是在编写必须处理文件系统的程序时一个不太常见但又很棘手的问题。默认情况下,Python 假定所有文件名都已经根据 sys.getfilesystemencoding()的值编码过了。但是,有一些文件系统并没有强制要求这样做,因此允许创建文件名没有正确编码的文件。这种情况不太常见,但是总会有些用户冒险这样做或者是无意之中这样做了 ( 可能是在一个有缺陷的代码中给 open() 函数传递了一个不合规范的文件名)。
当执行类似 os.listdir() 这样的函数时,这些不合规范的文件名就会让 Python
陷入困境。一方面,它不能仅仅只是丢弃这些不合格的名字。而另一方面,它又不能将
这些文件名转换为正确的文本字符串。Python 对这个问题的解决方案是从文件名中获取未解码的字节值比如 \xhh 并将它映射成 Unicode 字符 \udchh 表示的所谓的”代理编码”。下面一个例子演示了当一个不合格目录列表中含有一个文件名为 bäd.txt(使用Latin-1 而不是 UTF-8 编码) 时的样子:
>>> import os
>>> files = os.listdir('.')
>>> files
['spam.py', 'b\udce4d.txt', 'foo.txt']
>>>
image.png
你在编写依赖文件名和文件系统的关键任务程序时,就必须得考虑到这个。否则你可能会在某个周末被叫到办公室
去调试一些令人费解的错误。
网友评论