Python编码问题

来源:互联网 发布:freemind软件 编辑:程序博客网 时间:2024/06/06 09:10

Python编码问题

众所周知,Python2上经常会出现编码问题而被人诟病,这也是Python3问世并且并不和Python2兼容的一个原因,然而,目前来说使用Python2的还是占据大多数,因此对于开发者来说编码问题在一段时间内还是不能忽略的。

Python2上的编码

Python2里面分为 strunicode两种string类型。

str相当于bytes, unicode相当于对字符串一种更高层的表示,使用‘u’作为前缀 。在一个 unicode 字符串中,你可以使用 \u 来插入任何的 unicode 代码。如:

st=u'\u7535\u98ce\u62476'
  • 如何转化

    • 如果想要在 unicode 和 bytes 间转换的话,每个都会有个方法。 Unicode 字符串会有一个 .encode 方法来产生 bytes , bytes 串会有一个 .decode 方法来产生 unicode 。每个方法中都会有一个参数,来表明你要操作的编码类型。
    • unicode 进行encode肯定会成功,但是str进行decode就不一定了,因为byte实际编码可能与指定编码不符或者说不兼容。因此,encode参数除了跟着编码还有一个可选项,用于如何处于无法解码的byte
    • strict(默认参数): 将会抛出一个异常
    • replace: 将会返回一个标准的替代字符。当编码的时候,替代值是一个问好,所以任何不能被编码的值将会产生一个 ”?”
    • xmlcharrefreplace: 将会产生一个完全替代的 HTML/XML 字符,所以 u01B4 将会变成 “&#436” (因为十六进制的 01B4 是十进制的 436 )。如果你需要将返回的值来输出到 html 文件中的话,将会非常有用。
    • Ignore: 会直接将不能解码的 bytes 丢掉。
  • 常见问题:python2在试图处理Unicode和str的时候会进行隐式转换

    • 利用将一个str和unicode拼接的时候,str会使用 sys.getdefaultencoding() (一般是ASCII)进行隐式解码变为unicode
    • 简单打印unicode字符串的时候输出总会是bytes,这是因为unicode总会在打印之前编码成byte串
    • 将str进行encode,也会发生一次隐式转化,原因是str不能被编码,所以str编码之气那需要先进行一次默认的decode,变成unicde然后再转为str串

python3相关变化

- Python 3 也有两种类型,一个是 Unicode(也就是str类型),一个是 byte 码。Python 2 中的 “str” 现在叫做 “bytes”,而 Python 2 中的 “unicode” 现在叫做 “str”。- 取消对 byte 字符串的自动解码。 如果你想要用一个 byte 字符串和一个unicode 相链接的话,你将会得到一个错误,不管你包含的内容是什么。- 读取文件的变化,Python对于读取文件有两种方式,一种是二进制,一种是文本。在 Python 2 中,它只会影响到行尾符号,甚至在Unix系统上的时候,基本没有区别。在 Python 3中。这两种模式将会返回不同的结果。当你用文本模式打开一个文件时不管是你是用的 “r” 模式或者是它默认的模式,读取成的文件将会自动转码成 unicode ,你将会得到 str 对象。如果你用二进制模式打开一个文,在参数中输入 “rb” ,那么从文件中读取的数据将会是 bytes ,对它们没有任何处理。

处理策略

  • 将输入的 bytes 马上解码成 unicode。你在程序中均使用 unicode ,当在进行输出的时候,尽早将之编码成 bytes 。制造一个 Unicode 三明治, bytes 在外, Unicode 在内。
  • 第二条规则是。你需要知道你现在处理的是哪种类型的数据,在你的程序中任何一个位置,你需要知道你处理的是 byte 串还是一个 unicode 串。它不能是一种猜测,而应该被设计好。另外,如果你有一个 byte 串的话,如果你想对他进行处理。那么你应该知道他是怎样的编码。
  • 第三。测试 Unicode 支持。使用一些奇怪的符号来测试你是否已经做到了以上几点。

实际遇到的问题

监控客户端(python)发送的数据给服务器(java)有一个字段(server_live_name)带有u前缀

问题原因:

server_live_name对应的值原本是一个list字段,python客户端会把这个list转为一个str发给乐志。如果采用str或者repr直接转化,那么返回的str内部一定含有额外的u表示,之后很难去掉。

解决方式

  • 用str或者repr的正确做法是把list里面的unicode挨个转化为str然后再对整个list调用str或者repr方法。
  • 然而这样会特别麻烦,还有一种做法是使用json,json可以把object转为str
    但是需要注意,使用
json.dumps(names)

返回的是str,names里面以前是unicode的地方现在还是unicode。

json.dumps(names,ensure_ascii=False)))

返回的就是unicode,只要对此在做一次编码utf-8即可完美传输。

原创粉丝点击