专栏名称: 马哥Linux运维
马哥linux致力于linux运维培训,连续多年排名第一,订阅者可免费获得学习机会和相关Linux独家实战资料!
目录
相关文章推荐
运维  ·  再见,CDN 巨头:Akamai 宣布 ... ·  2 天前  
51好读  ›  专栏  ›  马哥Linux运维

Python Unicode编码混乱 :来自大洋彼岸的怨念

马哥Linux运维  · 公众号  · 运维  · 2018-10-12 22:11

正文

Unicode 已经解决了很多问题。知晓 ISO-8859-* CP437 带来的混乱 (当然对于非西方语言来说更糟糕) 的人都可以证明这一点。当然,这些天他们正在做一项有的益工作——编码表情符号。


除表情符号之外,一切并不那么顺畅。今日 Python 3 带来的痛苦更是一言难尽。


Python 决定将 Unicode 完全集成到语言中。听起来很不错吧?


但众多问题也随之而来。


例如,将带有智能引号的“播客”标题转为以 ASCII 编码会引致 python 错误,导致 gPodder 一款开源的播客接收器,采用 Python PyGTK 开发,可帮助管理播客 RSS 供稿,并自动下载所需要的播客资料 经常通过回溯退出。接着 pexpect 文档会告诉你用 logfile = sys.stdout 来显示与虚拟终端的交互。 就是这个在这些天引发了一个错误


文件名的处理可谓糟糕透顶。我最近处理了 20 年前当 UTF-8 还未成为文件名标准时的数据。这些文件名在 UNIX 上仍然有效,可以用 tar 命令进行压缩或解压。但当你试图将文件名以字符串的形式存储,编码错误便接踵而至。要想让 Python 程序正确地支持所有有效的 Unix 文件名,必须使用“ bytes ”而不是字符串,这可真够烦人的。所有 Python 程序正确的几率又能达到多少呢?我敢打赌,不会高的。


我最近正在处理 mtree 生成的数据,它使用八进制转义来处理文件名中的特殊字符。我认为这对于 Python 会很容易。结果

  • 许多错误的解答 ——对于某些值,你会得到一个编码错误。甚至那个页面上的正则表达式解决方案也不起作用。

  • 甚至存在更多错误的解答


第二个链接提到了一个未记录的函数—— codecs.escape_decode ,可正确解决这一问题。我最终不得不这样做:

而且,无论做什么,不要轻易写 if filetype=="file" ——这总被求值为 False ,因为 "file" 在逻辑运算时不同于 b"file" 。呃 好吧,我承认,自己一开始没注意到,踩过这坑…

因此,如果希望在 Python 中正确处理 Unix 文件名,你必须:

  • 有一个完全避免 Python 字符串的处理路径。

  • 使用 sys.{stdin,stdout}.buffer 而不是简单的 sys.stdin/stdout

  • 必须将文件名以字节形式提供给各种函数 。详情请参阅 PEP 0471 :“与 os 模块中的其他函数一样, scandir() 接受一个 bytes str 类作为路径参数,并返回与路径类型相同的 DirEntry.name DirEntry.path 属性。但是,强烈建议使用 str 类型,因为这样可以确保 Unicode 编码的文件名得到跨平台支持 (在Windows上,Python 3.3开始,就已经不支持bytes编码的文件名了)。 所以,如果你想跨平台,那就更糟了,因为不能在 Unix 上使用 str 也不能在 Windows 上使用 bytes

更新:你想在命令行上接收文件名吗? 我会把 这个烂摊子 交给你的。环境呢? 甚至都不清楚呢 !


小编说两句 :这事儿真不怪Python,题主这种“ 处理了 20 年前当 UTF-8 还未成为文件名标准时的数据 ”的任务,平时谁会碰到,这种任务当然需要题主对编码系统足够了解才能完成了......题主发发牢骚,别怨Python......


英文原文:http://changelog.complete.org/archives/9938-the-python-unicode-mess
译者:盈韬
来源:Python程序员



《Linux云计算及运维架构师高薪实战班》2018年11月26日即将开课中, 120天冲击Linux运维年薪30万







请到「今天看啥」查看全文