原文网址: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. 23.FutureTask基本操作总结

    1.FutureTask简介 在Executors框架体系中,FutureTask用来表示可获取结果的异步任务.FutureTask实现了Future接口,FutureTask提供了启动和取消异步任务 ...

  2. 网络编程之socketserver初识

    网络编程之socketserver初识 Server #!/usr/bin/env python # @Author : "Wjl" # @Date : 2017/12/22 # ...

  3. C++复习1.内存管理的知识

    C++ 内存管理 1.内存分配的方式有三种: 从静态存储区分配:在程序编译期间已经分配好了,这些在程序的生命周期内都是有效的,如全局变量,static变量 一个例子: char * p = " ...

  4. 【hdu1005】Number Sequence

    题目描述 一个数列的定义如下: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. 给出A和B,你要求出f(n). 输入 输 ...

  5. 学习写domready

    原视频参考http://www.imooc.com/learn/488 --博主个人尝试学习写的-- /** * Created by ty on 2016/1/3. */ //尝试自己写domrea ...

  6. linux系统参数统计脚本

    #!/bin/sh clear if [[ $# -eq 0 ]] then #Define Variable Reset_terminal Reset_terminal=$(tput sgr0) # ...

  7. SpringAnnotation注解之@Autowired

    @Autowired:自动装配,不用在bean里写<property>属性来指定所依赖的属性 1 2 3 4 @Autowired public void setUserDao(UserD ...

  8. Systems

    package com.System; public class Study01 { /* * System 包含一些游泳的类字段和方法 * 继承自java.lang包 * JDK1.0开始 * 全部 ...

  9. 解决chrome报Not allowed to load local resource错误的方法

    最近项目中遇到了关于图片的更改->保存->本地读取 在本地读取的环节上面出现了错误,一开始用的是直接本地路径,但是在页面上调试的出现了下面的错误,他的路径还是相对路径,下图所示: Goog ...

  10. 前端中CSS属性大全

    css属性 布局常用样式属性: width 设置元素(标签)的宽度,如:width:100px; height 设置元素(标签)的高度,如:height:200px; background 设置元素背 ...