Python攻克之路-Py编码续
1.py2和py3编码实例
linux上例子
[root@node2 coding]# cat coding.py
#!/usr/local/python3/bin/python3
f=open('test','r')
print(f.read())
[root@node2 coding]# python3 coding.py
你好吗?
windows上例子
coding.py
f=open('test','r',encoding='utf8')
print(f.read())
[root@node2 coding]# python3 coding.py
你好吗?
Issuse: 在python3上正常,在python2上出现报错
2.编码
分析:写的程序要转换成计算机可识别的内容,将人类可以认识的转换成计算机的二进制


3.Python2编码
str和unicode都是bosestring的子类.严格意义上说,str其实是字节串,它是unicode经过编码后的字节组成的序列.对UTF-U编码的str'李'使用len()函数时,结果是3,因为utf8编码的'李'='\xe8\x8b\x91'.
而unicode是一个字符串,str是unicode这个字符串经过编码(utf8,gbk等)后的字节组成的序列.如上面utf8编码的字符串'汉'.
unicode才是真正意义上的字符串,对字节串str使用正确的字符编码进行解码后获得,并且len(u'李')==1.
在python2,str=bytes.
Python2编码的最大特点是Python2将会自动的将bytes数据解码成unicode字符串,所以在python1可以将字节与字符串拼接
字节存储
>>> s='李明' #Py2中存的是字节串 >>> print len(s) 6 #存的是字节,汉字对应是3个字节 >>> print type(s) <type 'str'> #数据类型是str >>> print repr(s) '\xe6\x9d\x8e\xe6\x98\x8e' #内存中存储的内容,三个对应1个汉字
unicode存储
>>> s=u'李明' >>> print repr(s) u'\u674e\u660e' >>> print type(s) <type 'unicode'> #万国码,开始时只有英文,1个字节就可以了,涉及其他国家时不够用,进行扩展
summary
a. 无论是什么字符,在unicode上都有对应,u674e代指一个符号,英文没变化是在ACSII码上有对应
Python2
不同数据类型可以拼接
>>> print 'hello'+u'lin' #bytes类型与unicode,两个不同类型拼接应该报错,但是在py2中做了一个转换,把bytes转换unicode hellolin >>> print '刘' 刘 #按原理应该存的是字节,就应该返回字节,不应该打印出来汉字,print中个str,出来的实际是unicode数据类型,bytes是无法看到
只能把ASCII码的内容转换,脱离无法转(中文,日语等)
>>> print '刘' +u'林' Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)
unicode与str的关系
py2与py3区别:python3中把bytes与unicode做了一个严格的区分,内部不作转换,程序员自行转换 python2 >>> print 'hello'+u'lin' hellolin
4.Python3编码
python3 renamed the unicode type to str, the old type has been replaced by bytes
跟python2类似,python3也有两种类型,一个是unicode,一个是byte码.但是他们不同的命名
现在你从普通文本转换成"str"类型后存储的是一个unicode,"bytes"类型存储是byte串.你也可以通过一个b前缀制造byte串。
Python3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分.文本总是unicode,由str类型表示,二进制则由bytes类型表示,
python3不会以任意隐式滥用str和bytes,正是这使得两者区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串(反之亦然),也不能将字符串传入参数为字节包的函数(反之亦然),这是件好事
python3(拼接时要自行转换)
>>> print(b'hello'+'hello') #u是常用可以不加,使用bytes与计算机交互,加b Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can't concat str to bytes
实例
In [1]: s='李林'
In [2]: b1=s.encode('utf8')
In [3]: print(b1,type(b1))
b'\xe6\x9d\x8e\xe6\x9e\x97' <class 'bytes'>
In [4]: b1.decode('utf8')
Out[4]: '李林'
In [6]: b1.decode('gbk') #这时的b1是unicode
Out[6]: '鏉庢灄'
In [7]: b2=s.encode('gbk')
In [8]: print(b2,type(b2))
b'\xc0\xee\xc1\xd6' <class 'bytes'>
In [9]: print(b2.decode('gbk'))
李林
查看对应的unicode
In [10]: import json In [11]: print(json.dumps(s)) "\u674e\u6797"
查看Bytes
In [12]: bytes(s,'utf8') Out[12]: b'\xe6\x9d\x8e\xe6\x9e\x97' 从bytes到utf8 In [15]: b=bytes(s,'utf8') In [16]: str(b,'utf8') Out[16]: '李林'
在python2中默认是不能打印中文的
[root@node2 py]# cat en-decode.py #!/usr/bin/python print '李林' [root@node2 py]# python en-decode.py File "en-decode.py", line 2 SyntaxError: Non-ASCII character '\xe6' in file en-decode.py on line 2, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details [root@node2 py]# cat en-decode.py #!/usr/bin/python #coding:utf8 ########### print '李林' [root@node2 py]# python en-decode.py 李林
5.Issues
a. 在python2中打印中文时为什么要加coding:utf8(实际是将默认的ASCII修改成utf8)
分析:是在python2的解释器中执行,因为解释器默认编码是ASCII,ASCII中没有中文
[root@node2 py]# python Python 2.7.5 (default, Aug 4 2017, 00:39:18) >>> import sys >>> print sys.getdefaultencoding() #打印当前解释器的编码方式 ascii [root@node2 py]# python3 Python 3.6.5 (default, May 5 2018, 16:40:07) >>> import sys >>> print (sys.getdefaultencoding()) utf-8
b. 点py的文件保存在磁盘的内容与执行时放在内存中的内容是否一致
分析:使用coding:utf8时,告诉解释器要按utf8来执行,同时文本应该也要支持utf8,当文件保存在磁盘时,编码方式与使用的软件有关,如使用pycharm(或sublime、notepad++)操作时,使用的utf-8,保存时就是utf8,所以当解释器解释时,也要与文件保存的格式保持一致,如果要在windows运行也要一致
顺序:保存文件时决定的编码格式,然后解释器再根据保存的编码方式进行解释运行
c. 文件以utf8编码放入到磁盘中,再使用utf8去解释,解释的过程,文件中的内容应该都是utf8,但是中文却是unicode
分析:在python2或3中,把字符串'李林'放入一个内存地址中,而且是以unicode编码方式存,主要是世界公认
d. f.open()是按操作系统默认的编码方式运行的

浙公网安备 33010602011771号