原文网址:http://blog.csdn.net/trochiluses/article/details/16825269

摘要:在进行python脚本的编写时,如果我们用python来处理网页数据或者进行与中文字符有关的处理工作,经常出现这样的出错信息:SyntaxError: Non-ASCII character '\xe6' in file ./filename.py on line 3, but no encoding declared。本文主要讲解python中与unicode和中文、特殊字符编码有关的问题。字符编码和解码需要遵循什么规律?

前言:

如果密码领域一样,从明文到密码是加密,从密码到明文是解密。在python中,编码:unicode-->str;解码str-->unicode.既然是编码,那么就和密码领域一样,编码和解码自然涉及到编码/解码方案(对应加密或者解密算法),unicode相当于明文。在python中,编码函数是encode(),解码函数是decode()。需要注意的一点是,如果我们调用str.encode(),这里涉及到一个隐士的类型转化,会现将str转化成unicode,才能进行编码,这也是不太容易理解的地方。所以,str.encode()实际上就等价于str.decode(sys.defaultencoding).encode().而sys.defaultencoding一般是ascii,它是不能用来编码中文字符的。

在阅读本文之间,如果你对字符编码不是很熟悉,有必要先了解以下字符编码。可以参考:字符编码简介

1.一个中文字符编码问题

一个python脚本如下:

  1. #!/usr/bin/python
  2. string='我的'
  3. print string

运行脚本,提示信息如下:

SyntaxError: Non-ASCII character '\xe6' in file ./filename.py on line 3, but no encoding declared

出错原因:python默认采用ascii编码,而中文编码不再ascii编码能够表示的范围之内,所以string无法将“我的”作为ascii编码保存为str类型。

解决办法:采用中文字符编码,在脚本第二行加入编码类型,如下:

  1. #!/usr/bin/python
  2. #coding=gbk
  3. string='我的'
  4. print string<span style="font-size:14px;">
  5. </span>

这里,coding同样可以采用utf-8等能够编码中文字符的模式。

2.python的对字符的编解码

字符编码/解码函数:

1)unicode:这个是python的内建函数,位于unicode类。

unicode(string [, encoding[, errors]]) -> object

这个函数的作用是将string按照encoding的格式编码成为unicode对象。

省略参数将用python默认的ASCII来解码

2)decode:位于unicode类中。

decode(...)
 |      S.decode([encoding[,errors]]) -> string or unicode

|      
 |      Decodes S using the codec registered for encoding.

  1. #!/usr/bin/python
  2. #coding=gbk
  3. string='我的'
  4. print string
  5. s1=unicode(string,"gbk")
  6. s2=string.decode("gbk")
  7. print s1
  8. print s2<span style="font-size:14px;">
  9. </span>

这段代码的输出如下:
我的
鎴戠殑
鎴戠殑

显然,输出好像没有达到我们的期许的结果。为什么s1和s2输出的是乱码呢?string是str,print输出到屏幕,这个终端采用的字符编码有关。为什么string是正常的,而s1和s2都是乱码呢?我们接下来分析.

另外,你有没有觉得奇怪:为什么str类经过编码和解码以后的对象都是unicode呢?

答案:str.encode()实际上就等价于str.decode(sys.defaultencoding).encode().而sys.defaultencoding一般是ascii,它是不能用来编码中文字符的。

3)decode和encode都可以用于常规字符串和unicode字符串

但是:

str.decode()和unicode.encode()是直接正规的使用。

unicode.decode()会先将unicode转化成str,然后再执行decode()。

这里面涉及隐式类型转化的问题

3.codec是什么

Codec是把Coder/DECoder得首字母组合,它定义了文本跟二进制的转换方式,跟ASCII那种用一个字节把字符转换成数字的方式不同,Unicode用的是多字节,这导致了Unicode支持多种不同的编码方式,比如说codec支持的四种耳熟能详的编码方式是:ASCII,ISO8859—1/Latin-1,UTF-8,和UTF-16

最著名的是UTF-8编码,它也用一个字节来编码ASCII字符,这让那些必须同时处理ASCII码和Unicode码文本的程序员的工作变得非常轻松,因为ASCII字符的UTF-8编码和ASCII编码完全相同。

UTF-8编码可以用1到4个字节来表示其他语言的字符,这给那些需要直接处理Unicode数据的程序员带来了麻烦,因为他们没有办法按照固定长度逐一读出各个字符,幸运的是我们不需要掌握直接读取Unicode数据的方法,Python已经替我们完成了相关细节,我们无需为处理多字节字符的复杂问题而担心。

UTF-16也是一种变长编码,但是它不常用。

4.编码与解码

Unicode支持多种编码格式,这为程序员带来了额外的负担,每当你向一个文件写入字符串的时候,你必须定义一个编码用于把对应的Unicode内容转换成你定义的格式,Python通过Unicode字符串的encode()函数解决了这个问题,该函数接受字符串中的字符为参数,输出你指定的编码格式的内容。

所以,每次我们写一个Unicode字符串到磁盘上我们都要用指定的编码器给他“编码“一下,相应地,当我们从这个文件读取数据时,我们必须”解码”该文件,使之成为Unicode字符串对象。

5.python对unicode的支持

 

内建的unicode()函数:将一个string类型的字符串转变成一个unicode对象

decode/encode方法:用于将str对象转化成unicode对象,或者相反。

来看下面这一行例子:

  1. #!/usr/bin/python
  2. #coding=gbk
  3. string='我的'
  4. print "string is:",type(string)
  5. print string
  6. ustring=u"我的"
  7. print "ustring is:",type(ustring)
  8. print ustring
  9. gbkstring=ustring.encode("gbk")
  10. print "gbkstring is:",type(gbkstring)
  11. print gbkstring
  12. anotherstring=gbkstring.decode("gbk")
  13. print "anotherstring is:",type(anotherstring)
  14. print anotherstring<span style="font-size:14px;">
  15. </span>

输出结果如下:

string is: <type 'str'>
我的
ustring is: <type 'unicode'>
鎴戠殑
gbkstring is: <type 'str'>
我的
anotherstring is: <type 'unicode'>
鎴戠殑

任何两种字符编码之间如果想完成转化,必须要通过unicode这个桥梁,先把它抓化成unicode对象;unicode对象直接进行输出,往往会出现乱码,需要解码成str对象。另外需要注意:unicode对象,gbk编码,ascii编码,str对象这四个不同的概念。注意区分什么是字符串类型,什么是编码类型。

6.注意事项

关于字符编码的原理,可以参考这里:

在python中需要使用unicode需要注意:

1 程序中出现字符串时一定要加一个前缀u

2 不要用str()函数,用Unicode()代替

3 不要用过时的string模块。如果传给它非ASCII码,它会把一切搞砸。

4 不到必须时不要在你的程序里编解码Unicode字符,只在你要写入文件或者数据库或者网络时,才调用encode()函数和decode()函数。

5.使用什么字符编码,就要采用对应的字符集进行解码

内建的str()函数和chr()函数不能处理Unicode,它们只能处理常规ASCII编码的字符串,如果一个Unicode字符串作为参数传给了str()函数,它会首先被转换成ASCII码字符串然后交给str()函数。

7.关于linux终端的字符编码

终端等默认语言设置在/etc/environment之中,在linux下,如果terminal采用的是utf-8编码,那么如果我们的中文采用gbk编码,很有可能在输出到屏幕的时候产生乱码。

使用locale命令,可以查看与语言有关的环境变量:

  1. hyk@hyk-linux:~/program/python/chapter6
  2. $ locale
  3. LANG=zh_CN.UTF-8
  4. LANGUAGE=zh_CN:en_US:en
  5. LC_CTYPE="zh_CN.UTF-8"
  6. LC_NUMERIC=zh_CN.UTF-8
  7. LC_TIME=zh_CN.UTF-8
  8. LC_COLLATE="zh_CN.UTF-8"
  9. LC_MONETARY=zh_CN.UTF-8
  10. LC_MESSAGES="zh_CN.UTF-8"
  11. LC_PAPER=zh_CN.UTF-8
  12. LC_NAME=zh_CN.UTF-8
  13. LC_ADDRESS=zh_CN.UTF-8
  14. LC_TELEPHONE=zh_CN.UTF-8
  15. LC_MEASUREMENT=zh_CN.UTF-8
  16. LC_IDENTIFICATION=zh_CN.UTF-8
  17. LC_ALL=

python的print方法,会自动将相关的字符编码,转化成该环境变量对应的字符编码,所以使用print 可能会出现乱码和报错;但是使用write却不会。

8.python中关于字符处理的出错与解决办法

 

问题一:

  1. 13 strencode=string.encode("utf-8")
  2. 14 print "strencode is : ",type(strencode)
  3. 15 print strencode

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 4: ordinal not in range

解释:str本身是不能encode的,如果想要encode,先要转化成unicode,此时采用默认的ascii进行转化,所以就出错了。

解决办法:

1)指明str转化成unicode的编码方式:

  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. s = '中文'
  4. s.decode('utf-8').encode('gb18030')

2)重置变量 sys.defaultencoding

  1. import sys
  2. reload(sys) # Python2.5 初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入
  3. sys.setdefaultencoding('utf-8')
  4. str = '中文'
  5. str.encode('gb18030')

参考文献:

【1】字符编码简介:http://blog.csdn.net/trochiluses/article/details/8782019

【转】python 字符编码与解码——unicode、str和中文:UnicodeDecodeError: 'ascii' codec can't decode的更多相关文章

  1. python字符编码与解码 unicode,str

    解释以下几个问题: (1)python2中str和unicode是两种字符串类型,与字符编码方式是什么关系? (2)str和unicode是怎么相互转换的? (3)'\x...':'\u...', ' ...

  2. python 默认编码( UnicodeDecodeError: 'ascii' codec can't decode)

    python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: 'ascii' codec can't deco ...

  3. 【Python】【解决】UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 1: ordinal not in range(128)

    1.问题描述 今天在升级Ubuntu到14.04,使用命令行启动软件更新器,进行版本升级,结果开始升级就异常退出了,具体打印如下: $update-manager -d 正在检查新版 Ubuntu 使 ...

  4. 【Python】“UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9”根因及解决方法

    背景 自动化测试调用HTMLTestRunner生成测试报告的时候,出现了编码错误,错误如题 原因 搜索了很多资料,得出的结论是python的str默认是ascii编码,和unicode编码冲突,就会 ...

  5. 解决UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 12: ordinal not in range(128)的编码问题

    当我在运行一个基于scrapy的爬虫时出现UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 12: ordina ...

  6. Python HTMLTestRunner生成网页自动化测试报告时中文编码报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6

    1. 由于使用Python Selenium做网页自动化测试时,有截取网页上的中文信息保存到测试结果中,最终出现编码错误如下: File "D:/PycharmProjects/AutoTe ...

  7. Python报错“UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)”的解决办法

    最近在用Python处理中文字符串时,报出了如下错误: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ...

  8. python 3以上版本使用pickle.load读取文件报UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 6

    python 3以上版本使用pickle.load读取文件报UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 6 ...

  9. Windows下使用pip安装python包是报错-UnicodeDecodeError: 'ascii' codec can't decode byte 0xcb in position 0

    先交待下开发环境: 操作系统:Windows 7 Python版本:2.7.9 Pip版本:6.1.1 其他环境忽略 在windows下使用pip下载python包,出现如下错误 Collecting ...

随机推荐

  1. 互换CapsLock和Ctrl键

    如果你没有HHKB键盘,完全可以利用系统自身的功能交换CapsLock和Ctrl键. macOS系统 在系统偏好设置里,点击“键盘”,在出现的画面点击右下角的“修饰键...”按钮,在这里可以配置这两个 ...

  2. find命令中选项-path和-prune的使用

    在Windows中可以在某些路径中查找文件,也可以设定不在某些路径中查找文件,下面用Linux中的find的命令结合其-path -prune参数来看看在Linux中怎么实现此功能.假如在当前目录下查 ...

  3. 使用VMware出现的各种问题

    ifconfig命令无效 解决办法:yum install net-tools ping不通 cd /etc/sysconfig/network-scripts ls查看所有文件名称,找到ifcfg- ...

  4. rsa加解密密钥生成命令

    (1)生成原始RSA私钥文件 rsa_private_key.pem(原始私钥) openssl genrsa -out rsa_private_key.pem 2048 (2)将原始RSA私钥转换为 ...

  5. linux杀毒软件clamav安装与使用

    #clamav安装与使用 ###第一步:Clamav下载http://www.clamav.net/downloads wget http://www.clamav.net/downloads/pro ...

  6. FortiDDoS是使用历史流量基线进行检测的

    Understanding FortiDDoS Detection ModeIn Detection Mode, FortiDDoS logs events and builds traffic st ...

  7. office套件

    一.PDF模块 使用PyPDF2模块 pip install PyPDF2 1.1 从PDF读取数据 直接读取,并打印出来.但是这种打印存在一个问题,不能中文字符 import PyPDF2 impo ...

  8. [VS]VS快捷键

    VS快速跳到某一行:CTRL+G VS鼠标移动到下一个高亮处:Ctrl+Shift+上下箭头 VS转到定义后返回:Ctrl+- VS折叠全部代码:Ctrl.M+Ctrl.O VS代码格式化:Ctrl. ...

  9. C++复习10.对象的初始化拷贝析构函数

    对象的初始化.拷贝构造和析构函数 20131002 构造函数.析构函数.赋值函数是类的基本函数.每一个类只有一个析构函数,但是可以有多个构造函数.多个赋值函数.一般如果类中没有显示的声明和定义上述函数 ...

  10. CF911A

    题解: 先按照a大小排序(要双关键字) 然后和a[1]一样的按照b减一减,取最小 代码: #include<bits/stdc++.h> using namespace std; ; in ...