zoukankan      html  css  js  c++  java
  • Python编码问题

    Python编码问题总结

    下面的文章和编码具体解释总结了常见字符编码后,这篇文章会对python中常见的编码问题进行分析和总结。因为python3.x版本号和python2.x版本号在字符编码方面有非常大差异,所以本文都是以Python2.7.5来分析2.x版本号中的字符编码问题。


    1.Python编码基础

    1.1 str和unicode

    python中有两种数据模型来支持字符串这样的数据类型,str和unicode,它们的基类都是basestring。

    比方s = "中文"就是str类型的字符串,而u=u"中文"就是一个unicode类型的字符串。unicode是由str类型的字符串解码后得到。unicode也能够编码成str类型。即

    str --> decode -->unicode
    unicode --> encode --> str

    严格来说,str或许应该叫做字节串,由于对于UTF-8编码的str类型"中文",使用len()函数得到的结果是6,由于UTF-8编码的str类型“中文”实际是"xe4xb8xadxe6x96x87"

    而对于unicode类型u“中文”(实际是u"u4e2du6587"),使用len()函数得到结果是2.

    1.2 头部编码声明

    在python源码文件里假设实用到非ascii字符,比方中文,那么须要在源码文件头部声明源码字符编码,格式例如以下:

    #-*- coding: utf-8 -*-

    这个格式看起比較复杂,事实上python仅仅检查#、coding,编码等字符串,能够简写成#coding:utf-8,甚至还能够写成#coding:u8。


    2.Python2.x常见编码问题

    2.1 头部编码声明和文件编码问题

    文件头部编码声明决定了python解析源代码中的str的编码选择方式,比方头部声明的是utf-8编码,则代码中s="中文"python就会依照utf-8编码格式来解析,通过repr(s)能够看到字符编码是"xe4xb8xadxe6x96x87"。假设头部声明的编码是gbk编码,则python会对s採用gbk编码解析。结果是"xd6xd0xcexc4"

    须要注意的是,文件本身的编码要跟文件头部声明编码一致,不然就会出现故障。

    文件本身的编码在Linux以下能够在vim下用命令set fenc来查看。

    假设文件本身编码是gbk。而源代码文件头部声明的编码是utf-8,这样假设源代码中有中文就会有问题了,由于本身中文str存储是依照gbk编码来的。而python在解析str的时候又以为是utf-8编码。这样就会报SyntaxError: (unicode error) 'utf8' codec can't decode byte错误。

    2.2 默认编码问题

    以下看个python默认编码导致的问题:

    #coding: utf-8
    u = u"中文"
    print repr(u) # u'u4e2du6587'
    
    s = "中文"
    print repr(s) # 'xe4xb8xadxe6x96x87'
    
    u2 = s.decode("utf-8")
    print repr(u2) # u'u4e2du6587'
    
    #s2 = u.decode("utf-8") #编码错误
    #u2 = s.encode("utf-8") #解码错误
    

    注意实例中凝视掉的2行代码,对于unicode最好不要直接调用decode。str最好不要直接调用encode方法。由于假设是直接调用。则相当于u.encode(default_encoding).decode("utf-8")。default_encoding是python的unicode实现中用的默认编码,即sys.getdefaultencoding()得到的编码,假设你没有设置过。那么默认编码就是ascii,假设你的unicode本身超出了ascii编码范围就会报错。同理,假设对str直接调用encode方法,那么默认会先对str进行解码。即s.decode(default_encoding).encode("utf-8"),假设str本身是中文,而default_encoding是ascii的话。解码就会出错,从而导致上面这两行会分别报UnicodeEncodeError: 'ascii' codec can't encode characters in position...错误和UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position...错误。

    上面样例中凝视掉的两行代码假设运行就会报错,当然,假设本身str或者unicode都在ascii编码范围。就没有问题。比方s = "abc"; s.encode("utf-8")就不会有问题。语句运行后会返回一个跟s的id不同的str。

    那假设要解决实例1中的问题,有两种方法,其一是明白指定编码,例如以下所看到的:

    #coding: utf-8
    u = u"中文"
    print repr(u) # u'u4e2du6587'
    
    s = "中文"
    print repr(s) # 'xe4xb8xadxe6x96x87'
    
    u2 = s.decode("utf-8")
    print repr(u2) # u'u4e2du6587'
    
    s2 = u.encode("utf-8").decode("utf-8")  # OK                                    
    u2 = s.decode("utf8").encode("utf-8")   # OK
    

    另外一种方法就是更改python的默认编码为文件编码格式,例如以下所看到的(这里仅仅所以要reload sys模块。是由于python初始化后删除了setdefaultencoding方法):
    #coding:utf-8                                                                   
    
    import sys 
    reload(sys)
    sys.setdefaultencoding("utf-8") #更改默认编码为utf-8
    
    u = u"中文"
    print repr(u) # u'u4e2du6587'
    
    s = "中文"
    print repr(s) # 'xe4xb8xadxe6x96x87'
    
    u2 = s.decode("utf-8")
    print repr(u2) # u'u4e2du6587'
    
    s2 = u.decode("utf-8")
    u2 = s.encode("utf-8")

    2.3读写文件编码

    採用python的open()方法打开文件时,read()读取的是str,编码就是文件本身的编码。而调用write()写文件时,假设參数是unicode,则须要用指定编码encode,假设write()參数是unicode并且没有指定编码,则会採用python默认编码encode后再写入。

    #coding:utf-8                                                                   
    f = open("testfile")
    s = f.read()
    f.close()
    print type(s) # <type 'str'>
    
    u = s.decode("utf-8") #testfile是utf-8编码
    f = open("testfile", "w")
    f.write(u.encode("gbk")) #以gbk编码写入,testfile为gbk编码
    f.close()

    此外,python的codecs模块提供了一个open()方法。能够指定编码打开文件。使用这种方法打开文件读取返回是unicode。

    写入时,假设write參数是unicode,则使用打开文件时的编码写入,假设是str,则先使用默认编码解码成unicode后再以打开文件的编码写入(这里须要注意假设str是中文,而默认编码sys.getdefaultencoding()是ascii的话会报解码错误)。

    #coding:gbk
    import codecs
    
    f = codecs.open('testfile', encoding='utf-8')
    u = f.read()
    f.close()
    print type(u) # <type 'unicode'>
    
    f = codecs.open('testfile', 'a', encoding='utf-8')
    f.write(u) #写入unicode
    
    # 写入gbk编码的str,自己主动进行解码编码操作
    s = '汉'
    print repr(s) # 'xbaxba'
    # 这里会先将GBK编码的str解码为unicode再编码为UTF-8写入
    #f.write(s) #默认编码为ascii时。这会报解码错误。
    f.close()


    3.參考资料

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    山寨 《寻找房祖名》
    css3 弹性效果上下翻转demo
    CSS3 Hover 动画特效
    判断一个字符串通过变化字符的位置,是否可以组成回文
    获取多个字符串中的共同字符
    转换为回文的步数
    IOS中图片的一些处理方法
    python django的一点笔记
    一个图片切割的例子
    一个批量修改文件夹中文件名的命令
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4637458.html
Copyright © 2011-2022 走看看