Python中的字符串编码是一个很让初学者费解头疼的问题,特别是遇到中文时相关处理经常抛出Exception。字符串到底以什么编码在Python内部进行处理,Python2.x中文编码如何安全的转换,Python 2.x与Python 3.x在编码方面的区别?本文接下来会一一进行讲解。
1、字符串在Python内部的编码
在Python内部字符串都是以unicode编码进行处理,即源码文件中的字符串首先都会被decode成unicode编码的字符串,之后Python内部再进行处理,用代码显示表示如下:
unicode_str = input_str.decode('utf8')
以上是将uft8编码的字符串input_str
转换为unicode,decode成功的前提是你得知道input_str
的原始编码,比如这里是utf8,否则会抛出UnicodeDecodeError
的异常。
2、Python源码字符串的编码
Python 2.x的默认编码格式是ascii,字符串在转换前均会decode成unicode。初学Python大家可能会编写如下的代码:
#!/usr/bin/python
s = '你好'
print s
会出现下面的异常:
SyntaxError: Non-ASCII character '\xe4'
这个是因为错误的将utf8编码的中文当成ascii解码。解决方法也很常规:在Python源码文件中声明编码格式,最常见的声明方式如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
3、字符串编码安全的转换方式
我们常见的字符串处理场景是这样的,从文件中或者中MySQL/Redis中load一段数据,做一些split、find之类的操作,这不是在代码文件中已有的变量,动态加载的字符串并不会自动decode成unicode编码。因此遇到中文时需要我们显示的使用decode函数处理。若已知load字符串的编码格式,直接转换即可。大部分情况下并不知道load字符串的编码,这里可以借住chardet插件检测字符串的原始编码:
// 安装chardet库
pip install chardet
result = chardet.detect(s)
// 检测结果
>>> result
{'confidence': 0.99, 'encoding': 'utf-8'}
confidence表示检测的准确率,encoding表示检测的编码,关于chardet的原理这里不说了。数据处理完了,如果需要再次存储,使用encode方法即可
// 将unicode编码转为目标编码:utf8
out_put = str.encode('utf8')
4、Python 2.x与Python 3.x区别
使用Python 3.x版本可以解决大部分编码问题,Python 3.x把系统默认编码设置为utf8,被单引号或双引号括起来的字符串,就已经是 Unicode 类型的str。文本字符和二进制数据区分得更清晰,分别用 str 和 bytes 表示。文本字符全部用 str 类型表示,str 能表示 Unicode 字符集中所有字符,而二进制字节数据用一种全新的数据类型,用 bytes 来表示。
终极原则:decode early, unicode everywhere, encode late
在输入或者声明字符串的时候,尽早地使用decode方法将字符串转化成unicode编码格式;然后在程序内使用字符串的时候统一使用unicode格式进行处理;最后,在输出字符串的时候,通过encode方法将字符串转化为你所想要的编码格式。
参考: