zoukankan      html  css  js  c++  java
  • python编码问题,从隐隐作痛到除去病根

     查阅的资料链接

    python编码为什么这么蛋疼

    python2.7手册str函数

     python源文件默认编码与内部默认编码

    源文件默认编码

    1.源文件默认编码为ASCII,所以,如果不显示声明当前代码用什么编码写的,python会用ASCII去解析,如果源文件中有UTF-8编码,由于ASCII不能翻译UTF8编码,则会报错了.

    #file test.py  使用UTF8保存
    a='a'
    b=''

    运行后

    SyntaxError: Non-ASCII character 'xe5' in file test.py on line 2, but no encodi
    ng declared; see http://python.org/dev/peps/pep-0263/ for details

    上面报错说character 'xe5'是非ASCII码,因为'xe5'是'好'的UTF8字节串的一部分

    如下

    在编码为UTF8的终端中打印''
    >>> a=''
    >>> a
    'xe5xa5xbd

    所以,当前的源文件是什么编码编辑的,一定要声明出来.比如

    #coding=utf-8 #先在这里声明a='好'
    print a

    这点python就不如php先进了,php在配置文件php.ini中已经默认指定了编码格式,从而无需在文件中指出(除非有需要)。 

    以上代码运行结果为

    E:qprworkEdit_laravelqingpr_python_task>python test.py
    濂

    发现乱码了,因为我的cmd终端编码为GBK,而我的脚本是用UTF8写的,cmd认不出来啦,该怎么办呢?

    我有以下几种解决方案

    方案1.调整终端默认编码,这点依个人需求来吧。

    方案2.让脚本迎合终端的口味,要么方案a:脚本就保存为GBK的,要么方案b:在需要终端显示的地方转一下码,我说下b方案

    #coding=utf-8
    import sys
    a='好'
    #这个文件是保存为UTF8编码,如果要在cmd上正常显示,需要转为GBK,
    aUnicode = a.decode('utf-8') #先解码为unicode,解码的时候要告诉python,a是一个utf8字节串,不要又以为是ASCII字节串
    aGBK=aUnicode.encode('GBK')#将unicdode编码的a再编码为GBK
    print aGBK

    以上有一个小插曲,我直接用a.encode('GBK')行吗?这样是不行的,因为编码(encode)是针对unicode而言的,必须对unicode编码,如果硬生生使用类似'我'.encode('GBK'),则会报错的

    如下

    >>> a='好'
    >>> a.encode('GBK')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xba in position 0: ordinal
    not in range(128)
    >>>

    看到了吧,python抛出了Unicode解码异常,python又说'ascii'怎么怎么样,为啥啊?

    因为python只会对unicode字符串进行encode,如果非要对字节串encode,则它会先把字节串decode,以下是伪代码

    a.encode('GBK')==(   a.decode('默认编码').encode('gbk')   )

    上面的unicode解码异常,也是在进行解码的时候抛出的,python认为a就是用默认编码,即ASCII编码的,可a是UTF8编码啊,'好'在ASCII中不存在,所以会报错

    方案3.我不管你终端什么编码,终端你都要给我正常显示.

    那就用最直接的unicode编码啦,让python自己根据系统的当前编码进行转码打印出来

    #coding=utf-8
    print u'我'

    当 print 一个unicode字符串时,打印出来的是unicode对应的系统编码的字符,从而不会乱码了

    衍生的一个小问题,我就是想看某变量unicode是啥样的,那就用reper函数(返回一个对象的字符串形式)

    >>> a=u'好'
    >>> a
    u'u597d'
    >>> print repr(a)
    u'u597d'

    和php做个比较,在命令行中运行php文件时,比如cmd中运行编码为UTF8的文件,即使是多字节字符,也不会乱码,我猜测这是因为php在输出内容给终端时,php内部对终端编码有检测和转换机制,这点python2.7并没有做到。python2.7很实诚,文件什么编码,我给终端就是什么编码。

    内部默认编码

    在终端的命令行模式编辑代码时,不需要再声明当前写代码时所用的编码,我猜是因为python在命令行模式时,直接读取当前系统的编码

    例如,windows的cmd下再查看'好'这个字

    在编码为GBK的终端(cmd)打印''
    >>> a=''
    >>> a
    'xbaxc3'

    可以看到在cmd中,'好'是两个字节,

    linux的shell中

    在编码为UTF8的终端中打印''
    >>> a=''
    >>> a
    'xe5xa5xbd

    linux的shell环境,默认编码为utf8,‘好’是三个字节

    需要注意的地方

    python内部默认编码为ASCII,导致使用一些函数时需要注意,比如str和unicode

    str函数,以字符串的形式返回对象的呈现(在我理解,就是人可以看的呈现),

    针对不同的对象,str有不同的操作方法,比如针对于string类型,它会原样返回

    对于function类型,str函数会以字符串的形式返回这个函数在内存中的位置

    string类型使用str函数时,注意一点,如果是unicode类型的字符串,一定注意当前的默认编码

    如下,我在cmd,编码为GBK,python默认编码为ASCII

    >>> a=u''
    >>> str(a)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'u597d' in position 0
    : ordinal not in range(128)
    >>>

    以上对unicode使用str函数时,这个转换涉及到默认编码内部首先进行这样的转换:unicodeStr.encode(defaultencoding).

    如果defaultencoding不是编写代码本身的编码,那就会抛出异常.

    所以,要设置defaultencoding,如下

    >>> import sys
    >>> reload(sys)
    <module 'sys' (built-in)>
    >>> sys.setdefaultencoding('GBK')  #规定默认编码为GBK
    >>> a=u''
    >>> str(a)  #这里就不会报错了
    'xc0xb2'
    >>> str(a)==a 
    True
  • 相关阅读:
    Java基础(九)
    Java基础(八)
    Java基础(七)
    Java基础(六)
    MyBatis的一级缓存和二级缓存
    安卓音频处理相关资料集合贴
    Android studio下gradle Robolectric单元测试配置
    【翻译】安卓新播放器EXOplayer介绍
    ActionBar compat 如何禁用ActionBar的显示/隐藏动画
    如何实现自定义的android WebView错误页
  • 原文地址:https://www.cnblogs.com/ch459742906/p/7817963.html
Copyright © 2011-2022 走看看