打印不合法的文件名

问题

你的程序获取了一个目录中的文件名列表,但是当它试着去打印文件名的时候程序崩溃, 出现了 UnicodeEncodeError 异常和一条奇怪的消息—— surrogates not allowed 。

解决方案

当打印未知的文件名时,使用下面的方法可以避免这样的错误:

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']
>>>

如果你有代码需要操作文件名或者将文件名传递给 open() 这样的函数,一切都能正常工作。 只有当你想要输出文件名时才会碰到些麻烦(比如打印输出到屏幕或日志文件等)。 特别的,当你想打印上面的文件名列表时,你的程序就会崩溃:

>>> for name in files:
...     print(name)
...
spam.py
Traceback (most recent call last):File "<stdin>", line 2, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode character '\udce4' in
position 1: surrogates not allowed
>>>

程序崩溃的原因就是字符 \udce4 是一个非法的Unicode字符。 它其实是一个被称为代理字符对的双字符组合的后半部分。 由于缺少了前半部分,因此它是个非法的Unicode。 所以,唯一能成功输出的方法就是当遇到不合法文件名时采取相应的补救措施。 比如可以将上述代码修改如下:

>>> for name in files:
... try:
...     print(name)
... except UnicodeEncodeError:
...     print(bad_filename(name))
...
spam.py
b\udce4d.txt
foo.txt
>>>

在 bad_filename() 函数中怎样处置取决于你自己。 另外一个选择就是通过某种方式重新编码,示例如下:

def bad_filename(filename):temp = filename.encode(sys.getfilesystemencoding(), errors='surrogateescape')return temp.decode('latin-1')

译者注:

surrogateescape:
这种是Python在绝大部分面向OS的API中所使用的错误处理器,
它能以一种优雅的方式处理由操作系统提供的数据的编码问题。
在解码出错时会将出错字节存储到一个很少被使用到的Unicode编码范围内。
在编码时将那些隐藏值又还原回原先解码失败的字节序列。
它不仅对于OS API非常有用,也能很容易的处理其他情况下的编码错误。

使用这个版本产生的输出如下:

>>> for name in files:
...     try:
...         print(name)
...     except UnicodeEncodeError:
...         print(bad_filename(name))
...
spam.py
bäd.txt
foo.txt
>>>

Python  UnicodeEncodeError 和 surrogates not allowed 报错处理相关推荐

  1. ubuntu18.04安装python的mysqlclient==1.4.6报错ERROR Command errored out with exit status 1python setup

    安装python的mysqlclient==1.4.6报错 环境: ubuntu18.04 python 3.7.2 Django 2.2 想要使用Django来操作MySQL,报错: LookupE ...

  2. python中引入包的时候报错AttributeError: module ‘sys‘ has no attribute ‘setdefaultencoding‘解决方法?

    python中引入包的时候报错AttributeError: module 'sys' has no attribute 'setdefaultencoding'解决方法? 参考文章: (1)pyth ...

  3. python下载第三方库的时候报错ERROR: Command errored out with exit status 1: python setup.py egg_info Check the

    python下载第三方库的时候报错ERROR: Command errored out with exit status 1: python setup.py egg_info Check the l ...

  4. Python 使用xlrd读Excel文件报错

    Python 使用xlrd读Excel文件报错:XLRDError: Unsupported format, or corrupt file: Expected BOF record; found ' ...

  5. 已解决Python pandas.read_excel读取Excel文件报错

    已解决(Python pandas.read_excel读取Excel文件报错)io = ExcelFile(io,storage_options=storage.options, engine=en ...

  6. python的Web框架Django运行报错:Invalid HTTP_HOST header: 'xxx.xx.xxx.xxx:8000'. You may need to add 'xxx.xx'

    python的Web框架Django运行报错:Invalid HTTP_HOST header: 'xxx.xx.xxx.xxx:8000'. You may need to add 'xxx.xx' ...

  7. python字符串拼接数字_解决Python中字符串和数字拼接报错的方法

    解决Python中字符串和数字拼接报错的方法 前言 众所周知Python不像JS或者PHP这种弱类型语言里在字符串连接时会自动转换类型,如果直接将字符串和数字拼接会直接报错. 如以下的代码: # co ...

  8. python 解决IndentationError: unexpected unindent的报错!和通用代码框架,import requests def getHTMLText(url)...的解释

    python报错IndentationError: expected an indented block. 解决办法很简单,是脚本缩进的问题,检查脚本缩进是否有空格和tab混用的情况或者是缩进明显不对 ...

  9. Python 用smtplib库发邮件报错:[WinError 10061] 由于目标计算机积极拒绝,无法连接。解决办法

    看了菜鸟的教程,有这段代码: mail = smtplib.SMTP("localhost") 然后就报错了.菜鸟的教程太老了,Python迭代这么快,根本跟不上. 把这个里面的参 ...

  10. Python 命令pip install pygame安装报错

    报错1如下: Traceback (most recent call last):File "c:\users\administrator\appdata\local\programs\py ...

最新文章

  1. 让别人不知道你的网站使用PHP
  2. TensorFlow官方文档中的sub 和mul中的函数已经在API中改名了
  3. 第三方登录(QQ登录)开发流程详解
  4. 中望cad插件_中望软件与狄诺尼达成战略合作,打造交通行业全国产CAD解决方案...
  5. 安全多方计算(MPC)从入门到精通:简易教程
  6. 国内首例:飞步无人卡车携手中国邮政、德邦投入日常运营
  7. CS229学习笔记(2)多变量线性回归
  8. spring in action 4 第6章 视图分发
  9. 问题解决之——未知usb设备设备描述符请求失败(Jlink驱动)
  10. 二次解析视屏 php,最新PHP二次视频解析源码 带后台版
  11. 什么是外贸网站?企业为什么要建设外贸网站?
  12. 彻底解决乱码问题(一):为何会出现乱码
  13. 吸引子传播(Affinity Propagation)算法
  14. vs项目筛选器显示错乱、只显示部分文件
  15. classes是什么意思怎么读_Classes是什么意思_Classes的翻译_音标_读音_用法_例句_爱词霸在线词典...
  16. cubase打开时,别的软件和网页无法正常播放视频。
  17. Mac如何找到和清理微信和QQ的缓存文件
  18. Uos统信系统 nginx
  19. 电商社区怎么做?看服饰大佬如何通过粉丝圈激活客户
  20. C语言程序设计基础OJ练习题(实验十结构体与共用体)

热门文章

  1. hdu5773 LIS+贪心
  2. b java 之 serviceLoader详解 serviceLoader.load(XXX.class)
  3. 如何用计算机算工资,个人工资计算器避税
  4. 图片批量添加水印批量加背景缩放批量合并工具picUnionV4.0
  5. linux下RabbitMQ的配置和安装
  6. 浏览器原理:6.3宏任务和微任务
  7. 计算机再带word打不开怎么办,Word文档打不开怎么办 Word打开出错的解决办法
  8. 浪潮云服务器安装win7系统,WIN7旗舰版操作系统中浪潮ERP_GS5.2安装说明.doc
  9. 高薪职位怎么找?你们来学学这3招
  10. -webkit-background-clip属性不生效问题