python的编码问题

4 篇文章 2 订阅

看了好几篇编码的文章,表示还是理不顺。。仅做一些记录。

一、unicode和utf-8

    unicode记录了全球的所有语言,包含了跟全球所有国家编码的映射关系。但是都用unicode来表示编码太占空间,就创建了其他的编码方案,如utf-8、gbk等。

    utf-8是根据内容来动态分配字节数记录内容。使用1、2、3、4个字节表示所有字符,优先使用1个字符、无法满足则使增加一个字节,最多4个字节。英文占1个字节、欧洲语系占2个、东亚语系占3个,其它及特殊字符占4个。

二、字符的记录

    要注意:

  1. 无论以什么编码在内存里显示字符,存到硬盘上都是2进制
  2. 存到硬盘上时是以何种编码存的,再从硬盘上读出来时,就必须以何种编码读(开头声明或转换),要不然就乱了

三、python中编码的转换

python中版本2和3的处理是不一样的,python3默认编码是unicode,python2默认编码是ascii码

由此会产生一些格式类型的差异。

  • python2
  1. python2的默认编码是ascii码,所以无法支持中文,程序若出现中文(不论是变量、赋值还是注释)就会报错。
    程序中想使用中文,必须声明文件头编码,且编码要和该程序文件的编码类型一致。
    如:
             程序文件是utf-8编码,程序起始就添加:#-*- coding:utf-8 -*-
             程序文件是gbk编码,程序起始就添加:#-*- coding:gbk -*-
  2. python2中有两种表示字符序列的类型:str和unicode。默认的str并不是字符串,而是一个byte数组,或者可以理解成一个纯ascii码字符组成的字符串。
  3. 由上一点,可知python2中b开头的数组(即bytes数组)和字符串str属于同一种类型;u开头的数组则是unicode类型。可以通过函数type进行查看。
  4. python中,可以调用函数实现unicode和utf-8/gbk等编码的转换,方法为:
    utf-8/gbk等编码的str、bytes    ---> decode('原始编码')  ---->unicode编码
    unicode编码                            --->encode('编码类型')   --- >指定编码的str

写个样例,其中程序文件charset-2.py是utf-8编码,在windows环境运行,windows控制台是gbk编码显示

#-*- coding:utf-8 -*-
 
aaa = "你好"
bbb = b"你好"
ccc = u"你好"

print "aaa---type: ", type(aaa)," content: ", aaa
print "bbb---type: ", type(bbb)," content: ", bbb
print "ccc---type: ", type(ccc)," content: ", ccc

print "++++++++++++++++++++++++++++++++++++++++++"
aaa_decode = aaa.decode("utf-8")
bbb_decode = bbb.decode("utf-8")
print "aaa_decode---type: ", type(aaa_decode)," content: ", aaa_decode
print "bbb_decode---type: ", type(bbb_decode)," content: ", bbb_decode

aaa = aaa_decode.encode("gbk")
bbb = bbb_decode.encode("gbk")
print "aaa---type: ", type(aaa)," content: ", aaa
print "bbb---type: ", type(bbb)," content: ", bbb

print "++++++++++++++++++++++++++++++++++++++++++"
ccc_encode = ccc.encode("utf-8")
print "ccc_encode---type: ", type(ccc_encode)," content: ", ccc_encode
ccc_encode = ccc.encode("gbk")
print "ccc_encode---type: ", type(ccc_encode)," content: ", ccc_encode


在windows的输出结果:


可发现:
         <1>代码7-9行,显示aaa和bbb都是str类型,ccc是unicode类型。因为程序设置的编码是utf-8,所以aaa和bbb在windows控制台无法显示,而ccc是unicode类型,支持范围比gbk更大,可以正常显示内容
         <2>代码12-15行,aaa和bbb可以用decode函数转化为unicode类型,可正常显示
         <3>代码17-20行,aaa_decode和bbb_decode现在是unicode编码,可以用encode转化为gbk编码,则可正常显示
         <4>代码23-26,则是unicode类型的转换;转为utf-8乱码,转为gbk可以显示

  • python3
  1. python3默认是unicode编码,支持中文,因此无需加编码头
  2. python3有两种表示字符序列的类型:str和bytes。
  3. 由2可知,u前缀的数组和无前缀的字符串,都是unicode类型;b前缀的数组是bytes,在python3中存储为ascii码,无法存储中文,即无法将中文赋值给bytes数组。
  4. python3中也有encode和decode,不过转成gbk、utf-8等编码是存放于bytes数组
    utf-8/gbk等编码的bytes     ---> decode('原始编码')  ---->  unicode编码,也就是python3的str
    unicode编码(str)           --->encode('编码类型')   --- >指定编码的bytes

写个样例

aaa = "你好"
# bbb = b"你好"  直接赋值中文会报错
bbb = b"Hello"
ccc = u"你好"

print ("aaa---type: ", type(aaa)," content: ", aaa)
print ("bbb---type: ", type(bbb)," content: ", bbb)
print ("ccc---type: ", type(ccc)," content: ", ccc)

print ("++++++++++++++++++++++++++++++++++++++++++")

aaa_utf8_bytes = aaa.encode("utf-8")
aaa_gbk_bytes = aaa.encode("gbk")
print ("aaa_utf8_bytes---type: ", type(aaa_utf8_bytes)," content: ", aaa_utf8_bytes)
print ("aaa_gbk_bytes ---type: ", type(aaa_gbk_bytes)," content: ", aaa_gbk_bytes)

ccc_utf8_bytes = ccc.encode("utf-8")
ccc_gbk_bytes = ccc.encode("gbk")
print ("ccc_utf8_bytes---type: ", type(ccc_utf8_bytes)," content: ", ccc_utf8_bytes)
print ("ccc_gbk_bytes ---type: ", type(ccc_gbk_bytes)," content: ", ccc_gbk_bytes)

print ("aaa_str:", aaa_utf8_bytes.decode("utf-8"), aaa_gbk_bytes.decode("gbk"))
# print ("aaa_str:", aaa_utf8_bytes.decode("gbk"), aaa_gbk_bytes.decode("utf-8")) 编码不同会报错
print ("++++++++++++++++++++++++++++++++++++++++++")

运行结果:

可发现:
      1.代码1-9行,无前缀字符串和unicode都是str类型;b前缀是bytes类型,且bytes无法直接赋值中文
      2.代码12-20行,aaa和ccc通过encode进行指定字符编码,会转化成相应编码的bytes类型
      3.代码22-23行,aaa相应编码的bytes类型通过decode函数可以转为unicode类型并输出,但需指定正确编码,否则会报错或解码成其它内容。
      4.bbb因为是bytes类型,转换成gbk、utf-8都是一样编码和内容。
         但从aaa的encode和decode变换,可知bytes无法直接赋值中文但能转换存储。

四、延伸

有个python3脚本,需读取txt文本内容,转化为gb2312编码进行处理。
执行时会提示异常,增加了errors = "ignore"参数即可。。
其中使用的函数bytes(str, "xxx_encode", errors = "ignore") 等价于encode(str, encoding="xxx_encode", errors = "ignore")函数,即把str类型转为bytes类型

with  open( "./file.txt", "r", encoding="utf-8") as fp:
    data=fp.read()

data_gbk_bytes= bytes(data, "gb2312", errors = "ignore")

===等价于===>

data_gb2312_bytes = data.encode("gb2312", errors = "ignore")


# str转bytes叫encode,bytes转str叫decode
# 我的理解,str和字符在python3中都是unicode编码的,encode就是将unicode的二进制内容转化为相应的编码的二进制内容

参考文章:

https://www.cnblogs.com/schut/p/8407258.html

https://blog.csdn.net/jobschen/article/details/79805955

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值