最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str

StringEncoding crifan 14499浏览 0评论

此文之前

在读此文之前,你需要了解一些基本的前提知识:

1. Python的两种版本,Python 2.x和Python 3.x,的划分,不了解的去参考:

【整理】总结Python2(Python 2.x版本)和Python3(Python 3.x版本)之间的区别

2.对于各种字符编码要有个基本的了解

比如:

通用的Unicode

Unicode的最常见的一种实现方式,UTF-8

Windows中的默认编码GBK

等等,有个基本的概念。

如果不了解,可以参考相关内容:

字符编码详解

Windows Cmd中:设置字符编码:简体中文GBK/英文

3.关于Python文件中,声明当前文件所使用何种编码,要清楚其含义

不了解的,去看:

【整理】关于Python脚本开头两行的:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用 – 指定文件编码类型

 

Python编解码简介

Python中,不论是Python 2.x还是Python 3.x中,总体上说,字符都只有2大类:

一类是通用的Unicode字符;

另一类是,(unicode被编码后的),某种编码类型的字符,比如UTF-8,GBK等等类型的字符;

 

但是呢:

Python 2.x,字符编码方面,设计的不好,导致经常,非常容易,出现一些字符编码解码方面的错误。

具体常见错误及解决办法,可参考:

【总结】Python中常见字符编码和解码方面的错误及其解决办法

 

而:

Python 3.x中,对于字符编解码方面的设计,的确先进和简洁多了,在使用过程中,也就很少再出现这类编码解码方面的错误了。

 

下面,就来对比一下:

 

Python 2.x的str和unicode和Python 3.x的bytes和str的详细对比

下面来简单介绍一下,Python 2.x和Python 3.x在字符编码方面的知识:

 

关键字

含义

具体的写法

两者之间如何互换

Python 2.xstr某种编码(UTF-8,GBK等)类型的字符串"python 2.x中,普通的,用引号括起来的字符,就是str;此时字符串的编码类型,对应着你的Python文件本身保存为何种编码有关,最常见的Windows平台中,默认用的是GBK"str->unicode:
【核心代码逻辑】
1.确保自己知道对应字符串,是什么编码的
2.然后使用yourStr.decode("yourKnownEncoding")
去解码为对应的unicode字符串
注:
yourKnownEncoding为你自己所已知的,该字符串的编码类型
3.然后继续你想要的各种处理

【完整代码】
参见下面的:python_2.x_str_to_unicode.py

 unicodeUnicode类型的字符串

有两种写法:

  • 前缀加u
    • u"Python 2.x中,在普通字符串,加上前缀u后,就表示字符串是Unicode类型了"
  • 用unicode()强制转换:
    • unicode("Python 2.x中,在普通字符串,加上前缀u后,就表示字符串是Unicode类型了")
      • 此种写法的前提是,python文件中指定了对应的编码类型;
      • 并且对应的python文件的确是以该编码方式保存的
unicode->str:

【核心代码逻辑】
1.先声明,或已获得了对应的,Unicode字符
2.然后用
unicodeVariable.decode("encodingType")
去编码为对应的encodingType类型的字符串。
其中encodingType常见的有UTF-8,GBK等等;

注:
将Unicode转换为什么编码,因实际情况而异;
即具体编码为什么类型,和你的实际使用的需求和目的有关;

3.然后再去做后续的,你自己想要的,任何的处理
包括将其保存到对应的文件,传递给后面的代码处理等。

注:
虽然上述说如果转换为GBK,用于在Windows的cmd中输出,只是为了演示的目的;
实际上输出,尤其是打印Unicode类型的字符的时候,Python系统会自动将Unicode编码为,与当前输出终端,相同的编码,然后再显示的;此处此即自动把Unicode编码为cmd的GBK然后再显示。

【完整代码】
参见下面的:python_2.x_unicode_to_str.py

     
Python 3.xbytes某种编码(UTF-8,GBK等)类型的字节序列

普通字符串加上字母b作为前缀,就是表示bytes字符串了。

需要注意的是:

  • bytes,都是某种特定的编码的字符串
  • bytes,如果写上对应的值的话,那么只能直接写ASCII字符串,即只能写英文单词这种
  • 而如果想要写中文汉字这种,需要写\xYY这种16进制的值的形式才可以
    • 其中\xYY的值到底是多少,是你自己去通过相应的办法,将其编码为特定类型的字符所获得的
    • 其中如何把字符串,转换为某种编码的bytes的值,可以参考下面的"str->bytes"中的代码
    • 一般来说,我们在实际编程中,所遇到的是,你自己需要知道当前获得的字符串变量,是bytes,并且知道其是什么编码,基本上就可以了,然后就可以用后面介绍的bytesVariable.decode("specificEncoding")去解码为你需要的Unicode的str字符串了
bytes->str:
【核心代码逻辑】
1.如果你要写对应的bytes变量,那么需要加上前缀字母b;

注意:
不过要注意的是,只能写英文单词,而不能直接写中文等非ASCII的字符。
如果非要写非ASCII字符,那么只能自己想办法先将其转化为对应某种编码的byte,内部存储的内容,是对应的各个字节,打印出来的效果就是\xYY这种十六进制的值。

其中:
如果把对应的中文转换对特定编码的bytes的16进制值,可以参考下面的"str->bytes"的代码。
2.然后用
bytesVariable.decode("specificEncoding")
去解码为对应的str(即Unicode字符串)
其中:specificEncoding是该bytes的编码。

3.然后你就可以拿着Unicode的str,去做你想要的事情了
比如常见的打印出来看看。

【完整代码】
参见下面的:python_3.x_bytes_to_str.py

 strUnicode类型的字符串

Python 3.x中,直接输出的字符串(被单引号或双引号括起来的),就已经是Unicode类型的str了。

当然,有一些前提:

  • Python文件开始已经声明对应的编码
  • Python文件本身的确是使用该编码保存的
  • 两者的编码类型要一样(比如都是UTF-8或者都是GBK等)

这样Python解析器,才能正确的把你所输出字符串,解析为对应的unicode的str

str->bytes:
【核心代码逻辑】
1.默认写出的字符串,已经就是str,即Unicode,的类型了。
或者你之前已经获得了对应的unicode的str了。

注:当然,如果在Python文件中,需要满足下列条件:
A。Python文件开始已经声明对应的编码
B。Python文件本身的确是使用该编码保存的
C。两者的编码类型要一样(比如都是UTF-8或者都是GBK等)

2.然后调用
unicodeStr.encode("encodingType")
去编码为对应的字节序列bytes,
3.然后后续再进行相应的你所需要的处理

【完整代码】
参见下面的:python_3.x_str_to_bytes.py

 

演示代码

1.下面是上面相关的字符串转换,所用的示例代码。

如下代码,分别在:

Python 2.7.2

Python 3.2.2

中测试通过。

2. 你可以把如下对应的代码,保存为对应的文件。

其中,需要注意对应的Python文件所使用的编码,需要和其声明的编码(UTF-8)一致。

换句话说,你要把代码保存到UTF-8编码的Python文件中。

 

其中:

对于如何确保文件本身是何种编码的,以及如何转换为所需的编码类型,不了解的,可以参考:

用Notepad++实现不同字符编码之间的转换

3.如果你实在对编码不熟悉,那么直接下载对应的文件吧(右击另存为):

[   ] python_2.x_str_to_unicode.py

[   ] python_2.x_unicode_to_str.py

[   ] python_3.x_bytes_to_str.py

[   ] python_3.x_str_to_bytes.py

 

python_2.x_unicode_to_str.py

 

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str
https://www.crifan.com/summary_python_string_encoding_decoding_difference_and_comparation_python_2_x_str_unicode_vs_python_3_x_bytes_str

Author:     Crifan
Verison:    2012-11-29
-------------------------------------------------------------------------------
"""

def python2xUnicodeToStr():
    zhcnUnicode = u"1.此处是中文字符;2.而你之所以能正确看到此处中文字符,是因为(1)此处python文件中,通过开始的编码指定为UTF-8(2)并且本身Python文件也是UTF-8编码保存的;3.接下来将要演示的是,将此段中文字符,转换为GBK编码,然后在windows的cmd中输出;";
    print "type(zhcnUnicode)=",type(zhcnUnicode); #type(zhcnUnicode)= <type 'unicode'>
    zhcnGBK = zhcnUnicode.encode("GBK");
    print "You should see these zh-CN chars in windows cmd normally: zhcnGBK=%s"%(zhcnGBK); #You should see these zh-CN chars in windows cmd normally: zhcnGBK=1.此处是中文字符;...... 然后在windows的cmd中输出;
    
###############################################################################
if __name__=="__main__":
    python2xUnicodeToStr();

 

 

python_2.x_str_to_unicode.py

 

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str
https://www.crifan.com/summary_python_string_encoding_decoding_difference_and_comparation_python_2_x_str_unicode_vs_python_3_x_bytes_str

Author:     Crifan
Verison:    2012-11-29
-------------------------------------------------------------------------------
"""

def python2xStrToUnicode():
    strUtf8 = "1.此处是UTF-8编码的中文字符(之所以不是其他编码,是因为我们此处文件开头指定了是UTF-8,并且此Python文件本身也是以UTF-8编码保存的,这样才能确保Python解析器,正确解析本文件,及其所包含的字符);2.接下来将要演示的是,将此段UTF-8的中文字符,解码为对应的Unicode字符;3.然后输出到windows的cmd中(其中unicode字符在输出打印时,会自动转换为对应的(此处的GBK)编码的);";
    print "type(strUtf8)=",type(strUtf8); #type(strUtf8)= <type 'str'>
    decodedUnicode = strUtf8.decode("UTF-8");
    print "You should see these unicode zh-CN chars in windows cmd normally: decodedUnicode=%s"%(decodedUnicode); #You should see these unicode zh-CN chars in windows cmd normally: decodedUnicode=1.此处是UTF-8编码的中文字符 ...... 转换为对应的(此处的GBK)编码的);
    
###############################################################################
if __name__=="__main__":
    python2xStrToUnicode();

 

python_3.x_str_to_bytes.py

 

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str
https://www.crifan.com/summary_python_string_encoding_decoding_difference_and_comparation_python_2_x_str_unicode_vs_python_3_x_bytes_str

Author:     Crifan
Verison:    2012-11-29
-------------------------------------------------------------------------------
"""

def python3xStrToBytes():
    """Demo Python 3.x (unicode) str to bytes
    """
    
    zhcnUnicode = "1.此处的,Python 3.x中,默认字符串的写法,就已经是unicode类型的字符串了。2.当然,还是有一点前提的,那就是,你在(1)此处python文件所指定的编码类型(2)要和你当前python文件实际所采用的编码类型,要匹配和一致,即此处,两者均是UTF-8,所以,Python解析器,才能正确的将我们此处所输入的UTF-8的中文字符,正确地解码为对应的Unicode字符串的;3.接下来将要演示的是,打印对于的此处字符的类型;然后再直接输出显示到windows的GBK编码的cmd中";
    print("type(zhcnUnicode)=",type(zhcnUnicode)); #type(zhcnUnicode)= <class 'str'>
    zhcnGbkBytes = zhcnUnicode.encode("GBK");
    print("You should see these zh-CN bytes in windows cmd normally, which begin with b preffix: zhcnGbkBytes=%s"%(zhcnGbkBytes)); #You should see these zh-CN bytes in windows cmd normally, which begin with b preffix: zhcnGbkBytes=b'1.\xb4\xcb\xb4\xa6\xb5 ...... \xc2\xeb\xb5\xc4cmd\xd6\xd0'
    
###############################################################################
if __name__=="__main__":
    python3xStrToBytes();

 

python_3.x_bytes_to_str.py

 

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str
https://www.crifan.com/summary_python_string_encoding_decoding_difference_and_comparation_python_2_x_str_unicode_vs_python_3_x_bytes_str

Author:     Crifan
Verison:    2012-11-29
-------------------------------------------------------------------------------
"""

def python3xBytesToStr():
    """Demo Python 3.x bytes to (unicode) str
    """
    
    #此处的bytes,只能接受ASCII字符
    #想要输入非ASCII的字符,则只能通过\xYY的十六进制方式输入,其中YY为对应的16进制的值
    #此处,我是已经在别处,通过把对应的中文:
    #"1.Python 3.x中,给字符串前面添加字母b,表示是bytes的字符串;2.此处之所以可以实现,接下来的,Python解析器,可以正确的将bytes解码为Unicode的str,那是因为(1)此处python文件所指定的编码类型(2)要和你当前python文件实际所采用的编码类型,是一致的,都是UTF-8;3.接下来将要演示的是,将此bytes字符串,解码为Unicode的str,然后在此处的终端,windows的默认编码为GBK的cmd中显示出来;";
    #解析为UTF-8的bytes了,所以下面你看到的是,解析后的,一堆bytes
    
    zhcnBytes = b"1.\xe6\xad\xa4\xe5\xa4\x84\xe7\x9a\x84\xef\xbc\x8cPython 3.x\xe4\xb8\xad\xef\xbc\x8c\xe9\xbb\x98\xe8\xae\xa4\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xe7\x9a\x84\xe5\x86\x99\xe6\xb3\x95\xef\xbc\x8c\xe5\xb0\xb1\xe5\xb7\xb2\xe7\xbb\x8f\xe6\x98\xafunicode\xe7\xb1\xbb\xe5\x9e\x8b\xe7\x9a\x84\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xe4\xba\x86\xe3\x80\x822.\xe5\xbd\x93\xe7\x84\xb6\xef\xbc\x8c\xe8\xbf\x98\xe6\x98\xaf\xe6\x9c\x89\xe4\xb8\x80\xe7\x82\xb9\xe5\x89\x8d\xe6\x8f\x90\xe7\x9a\x84\xef\xbc\x8c\xe9\x82\xa3\xe5\xb0\xb1\xe6\x98\xaf\xef\xbc\x8c\xe4\xbd\xa0\xe5\x9c\xa8(1)\xe6\xad\xa4\xe5\xa4\x84python\xe6\x96\x87\xe4\xbb\xb6\xe6\x89\x80\xe6\x8c\x87\xe5\xae\x9a\xe7\x9a\x84\xe7\xbc\x96\xe7\xa0\x81\xe7\xb1\xbb\xe5\x9e\x8b(2)\xe8\xa6\x81\xe5\x92\x8c\xe4\xbd\xa0\xe5\xbd\x93\xe5\x89\x8dpython\xe6\x96\x87\xe4\xbb\xb6\xe5\xae\x9e\xe9\x99\x85\xe6\x89\x80\xe9\x87\x87\xe7\x94\xa8\xe7\x9a\x84\xe7\xbc\x96\xe7\xa0\x81\xe7\xb1\xbb\xe5\x9e\x8b\xef\xbc\x8c\xe8\xa6\x81\xe5\x8c\xb9\xe9\x85\x8d\xe5\x92\x8c\xe4\xb8\x80\xe8\x87\xb4\xef\xbc\x8c\xe5\x8d\xb3\xe6\xad\xa4\xe5\xa4\x84\xef\xbc\x8c\xe4\xb8\xa4\xe8\x80\x85\xe5\x9d\x87\xe6\x98\xafUTF-8\xef\xbc\x8c\xe6\x89\x80\xe4\xbb\xa5\xef\xbc\x8cPython\xe8\xa7\xa3\xe6\x9e\x90\xe5\x99\xa8\xef\xbc\x8c\xe6\x89\x8d\xe8\x83\xbd\xe6\xad\xa3\xe7\xa1\xae\xe7\x9a\x84\xe5\xb0\x86\xe6\x88\x91\xe4\xbb\xac\xe6\xad\xa4\xe5\xa4\x84\xe6\x89\x80\xe8\xbe\x93\xe5\x85\xa5\xe7\x9a\x84UTF-8\xe7\x9a\x84\xe4\xb8\xad\xe6\x96\x87\xe5\xad\x97\xe7\xac\xa6\xef\xbc\x8c\xe6\xad\xa3\xe7\xa1\xae\xe5\x9c\xb0\xe8\xa7\xa3\xe7\xa0\x81\xe4\xb8\xba\xe5\xaf\xb9\xe5\xba\x94\xe7\x9a\x84Unicode\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xe7\x9a\x84\xef\xbc\x9b3.\xe6\x8e\xa5\xe4\xb8\x8b\xe6\x9d\xa5\xe5\xb0\x86\xe8\xa6\x81\xe6\xbc\x94\xe7\xa4\xba\xe7\x9a\x84\xe6\x98\xaf\xef\xbc\x8c\xe6\x89\x93\xe5\x8d\xb0\xe5\xaf\xb9\xe4\xba\x8e\xe7\x9a\x84\xe6\xad\xa4\xe5\xa4\x84\xe5\xad\x97\xe7\xac\xa6\xe7\x9a\x84\xe7\xb1\xbb\xe5\x9e\x8b\xef\xbc\x9b\xe7\x84\xb6\xe5\x90\x8e\xe5\x86\x8d\xe7\x9b\xb4\xe6\x8e\xa5\xe8\xbe\x93\xe5\x87\xba\xe6\x98\xbe\xe7\xa4\xba\xe5\x88\xb0windows\xe7\x9a\x84GBK\xe7\xbc\x96\xe7\xa0\x81\xe7\x9a\x84cmd\xe4\xb8\xad";
    print("type(zhcnBytes)=",type(zhcnBytes)); #type(zhcnBytes)= <class 'bytes'>
    zhcnUnicodeStr = zhcnBytes.decode("UTF-8");
    print("You should see these zh-CN unicode str in windows cmd normally: zhcnUnicodeStr=%s"%(zhcnUnicodeStr)); #You should see these zh-CN unicode str in windows cmd normally: zhcnUnicodeStr=1.此处的,Python 3.x中 ...... 然后再直接输出显示到windows的GBK编码的cmd中
    
###############################################################################
if __name__=="__main__":
    python3xBytesToStr();

 

更多内容

其他还有一些供参考的内容,感兴趣的自己去看:

Python中的 UnicodeEncodeError

【已解决】Python字符串处理出现错误:UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe6 in position 0: ordinal not in range(128)

【整理】关于Python中自动识别字符串编码,并正确在cmd中输出的各种情况的测试

转载请注明:在路上 » 【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (6)

  1. 表格里面,python2.x里的unicode转str,写错了: “ 2.然后用 unicodeVariable.decode("encodingType") 去编码为对应的encodingType类型的字符串。 ” 这里应该用encode。
    shoryuken9年前 (2014-12-29)回复
    • 是的
      coco7年前 (2017-08-16)回复
89 queries in 0.199 seconds, using 22.27MB memory