wordpress注册添加算术验证码,东莞营销网站建设优化,网址域名注册,沈阳网站建设方法我们通常见到的字符串编码主要是三种GB2312/GBK、Unicode、UTF-8。GB2312/GBK是多字节(multibytes)编码的一种#xff0c;属于“ASCII的加强版”#xff0c;与之平行的由Big5、ShiftJIS之类的编码各自为政#xff0c;所有这些用两个字节表示汉字的多字节编码标准统称为ANSI编…
我们通常见到的字符串编码主要是三种GB2312/GBK、Unicode、UTF-8。GB2312/GBK是多字节(multibytes)编码的一种属于“ASCII的加强版”与之平行的由Big5、ShiftJIS之类的编码各自为政所有这些用两个字节表示汉字的多字节编码标准统称为ANSI编码同样的汉字在不同的ASNI编码中的表示是不同的。为了避免这个问题Unicode应运而生将全世界所有的字符统一编码到一个定长的结构中。Unicode解决了统一编码的问题但带来了新的问题。第一点Unicode和ASCII不兼容了这是因为ASCII只有一个字节而这一个字节肯定装不下Unicode。第二点用Unicode传输开销变大了这是因为很多文档二十六个字母1个字节就能解决了用Unicode多了很多冗余的字节。因此UTF-8应运而生。UTF-8对Unicode进行变长编码我们可以想象下Huffman树通常长度在1-4字节。目前Linux系统使用的是UTF-8编码而Windows内部则是UTF-16LE/GBK编码。
Python2的字符串表示
Python2中有表示字符串有str和Unicode两种。其中一个str字面量由表示我们也可以用或者这类括号括起一个Unicode字面量由u括起。1
2
3
4
5
6
7
8你好
xc4xe3xbaxc3
u你好
uu4f60u597d
type(你好)type(u你好)其中Unicode得益于ucs2/ucs4标准在不同系统上都是固定的表示的。其中ucs2即Unicode16比较常见用2个字节(65536)来索引一般表示是uuxxxxucs4即Unicode32一般表示是uUxxxxyyyy在一些Python中也能见到。我们可以通过下面的代码来检测Python是哪一个1
2
3
4
5
6
7
8
9--enable-unicodeucs4import sysprint sys.maxunicode
1114111
--enable-unicodeucs2import sysprint sys.maxunicode
65535
str的表示取决于所在的系统例如Linux是默认UTF8上面的“你好”就会变为/xe4/xbd/xa0/xe5/xa5/xbd我们这里看到UTF8确实是一种字符的表示。1
2
3
4
5
6
7
8
9
10
11 hello.encode(utf-8)
hellohello.decode(gbk).encode(utf-8)
hello你好.encode(utf-8)
Traceback (most recent call last):
File , line 1, in
UnicodeDecodeError: ascii codec cant decode byte 0xc4 in position 0: ordinal not in range(128)你好.decode(gbk).encode(utf-8)
xe4xbdxa0xe5xa5xbd
Python2中字符串问题实录
reload
在Python2中出现编码问题时很多人喜欢使用下面的语句来改变系统的默认编码1
2
3import sys
(sys)
sys.setdefaultencoding(utf-8)
这种策略通常用来解决下面这样的错误提示
UnicodeEncodeError: ascii codec cant encode byte
现在ASCII码不能encode是吧那我默认都用utf-8来encode总行了吧但这样可能存在问题博文中就举出了一个实例。对于多字节字符串str我们之前默认用ASCII解码要是解不开就RE了。现在我们默认用utf-8解utf-8阈值广基本都能解开不RE了可是就不WA了么样例中举出一个例子一个latin-1编码的字符串用utf-8解码不会报错但解出来的结果并不对。因此在多字节编码规则不统一这个客观问题存在的情况下不存在银弹。我们需要的是用chardet.detect来猜测编码。当猜测不出时我们只能不停地try直到找到一个解码不报错的编码虽然可能解出来还是乱码因为可能一段byte串同时用utf-8、gbk、Big5等都能解码而不报错。
这里提供一个工具类能够尽可能地猜测字节串所使用的编码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23def ultimate_decode(doc):
def try_decode(s, try_decoding):
try:
res s.decode(try_decoding)
return True, res
except UnicodeDecodeError:
return False,
if isinstance(doc, str):
predicted chardet.detect(doc)
print predicted
if predicted[encoding] and predicted[confidence] 0.5:
doc doc.decode(predicted[encoding])
else:
encodeing_list [utf-8, gbk, Big5, EUC-JP]
for e in encodeing_list:
state, res try_decode(doc, e)
if state:
doc res
break
if not isinstance(doc, unicode):
return None
return doc
coding
当我们在Python代码文件中需要加入中文时我们需要在文件开头加上这两行中的一行不然即使用上前面的reload大法都不行。1
2#-*- coding:utf-8 -*-
#coding: utf8
这是用来指定Python代码文件所使用的编码方式。在Python2.1时这个机制还没有引入我们只能通过unicode-escape的方式输入。一个类似的做法是很多json库dump的结果中常出现u打头的unicode-escape字符串这是非常正常的现象。这样json库可以省事地避免编码问题因为这样json文件现在都是ASCII码了。
伪装成Unicode的多字节
有时候我们会看到这种东西uxe3x80x8axe5首先这外面套了个u应该是Unicode但是里面却是x打头的multi-bytes的形式这往往是由于错误调用unicode()函数所致的。对此python提供了raw_unicode_escape来解决这个问题
正则匹配
由于存在特殊符号的原因使用正则匹配时宜使用Unicode而不是多字节匹配。但是以下的编码在Win10和某些Linux发行版上都跑不了但在MacOS和Ubuntu上能够正常运行去StackOverflow问了他们认为这是一个Bug所以暂时还是先用上面的方法。