问题引入

先看下面的代码,代码用utf8编码格式保存.

print("中")

仅有一行代码,但是这个代码无论在ubuntu下还是win7下都会报错,错误信息类似是下面的内容:

SyntaxError: Non-ASCII character '\xe4' in file xxx, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

错误的原因是python 2.7默认python代码中只有ASCII编码.而代码中有"中"这个汉字.python解释器处理到汉字时,发现ASCII码没办法表示,就报错了.修改如下:

# coding:utf-8
print("中")

加上# coding:utf-8意思是告诉python解释器,源代码的编码是utf-8,python解释器就用utf-8的形式处理源代码,utf-8可以表示"中"这个汉字.再在命令行窗口中运行代码,虽然不报错,且Ubuntu下显示正常,但是在windows命令行窗口中显示显示的不是汉字"中".为什么?这个涉及到的问题比较多,分步骤讨论.

str,unicode

str是字节组成的序列.需要强调的是,str必须显示或隐式地指定字符编码的时候,str和字符才能对应起来.同一个str,字符编码不同时,显示的内容就不同.这个非常容易理解,对于2个字节组成的str,utf-8和gbk代表的字符肯定是不一样的.python字符串默认是str型.之前的print("中")实际上输出的是str类型的字符串.看下面的代码.

# coding:utf-8
a = "中"
print(type(a))
print(len(a))

上面代码输出是str, 长度为3. str表示"中"是str类型,长度为3表示"中"由3个字节组成.内存中是以utf-8保存字符串的,"中"的utf-8编码是3个字节,所以len的输出为3.

再看下面代码

# coding:utf-8
a = u"中"
print(type(a))
print(len(a))

"中"之前加一个前缀u,声明这里的"中"是unicode类型.unicode类型的字符串有几个字符,长度就是几,可以直观地看出来,不用再纠结字符在内存中是几个字节.这样就大大减轻了程序员的思维负担.

print函数自动转码问题

写程序时经常会用print函数测试输出,这就涉及到输出内容的编码.看下面代码

# coding:utf-8
import sys
print (sys.stdout.encoding)

这个代码在windows下输出是cp936,Ubuntu下输出是utf-8. 参数是str类型或者unicode类型,print函数会做不同处理,分开讨论.

str

输入参数是str类型时,print函数会把str转成sys.stdout.encoding指定的编码输出.对于汉字"中",python解释器把汉字"中"转化成utf-8(源代码的coding:utf-8指定)编码,占3个字节,类型为str.调用print函数时,python解释器把这3个字节当成sys.stdout.encoding指定的编码输出.Ubuntu系统中sys.stdout.encoding为utf-8,,肯定正常,因为本身是按utf-8形式转成3个字节的,再以utf-8显示,没问题.Windows系统中,sys.stdout.encoding是cp936,本身那3个字节是表示一个utf-8编码,现在以cp936的形式输出,就得到一个奇怪结果.这就解释了第1部分中的问题.如果字节中有超出cp936编码的内容,会直接报错.

unicode

unicode就比较简单了,不存在转码的问题.输入的unicode编码是什么,就输出对应的字符.

解决问题

要想让在windows系统下正常显示"中",转下码就可以了.代码如下.

import sys
a = "中"
print a.decode("utf-8").encode(sys.stdout.encoding)

先转成unicode,再转成sys.stdout.encoding编码.可以unicode当成"中转站",任何编码都能转成unicode,unicode也能转成任何编码.这个思路在处理不同操作系统的路径问题时非常有用.

注意

  1. python 2中程序运行过程中应该使用unicode,最后返回结果时再根据需要转成utf-8或gbk.不要使用setdefaultencoding('utf-8'),原因见参考资料.
  2. 凡是和输出有关的最好都转化成sys.getfilesystemencoding()编码再输出.

参考资料

  1. Why does Python print unicode characters when the default encoding is ASCII?
  2. unicode编码列表
  3. GBK 编码
  4. 立即停止使用 setdefaultencoding('utf-8')以及为什么

python 2.7编码问题的更多相关文章

  1. python基础之编码问题

    python基础之编码问题 本节内容 字符串编码问题由来 字符串编码解决方案 1.字符串编码问题由来 由于字符串编码是从ascii--->unicode--->utf-8(utf-16和u ...

  2. Python基础-字符编码与转码

    ***了解计算机的底层原理*** Python全栈开发之Python基础-字符编码与转码 需知: 1.在python2默认编码是ASCII, python3里默认是utf-8 2.unicode 分为 ...

  3. python中的编码问题:以ascii和unicode为主线

      1.unicode.gbk.gb2312.utf-8的关系 http://www.pythonclub.org/python-basic/encode-detail 这篇文章写的比较好,utf-8 ...

  4. python与字符集编码

    讲的比较明白的博客:http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html 以上面博文的汉为例子,汉字的GBK编码是baba, UNIC ...

  5. 第三篇:python基础之编码问题

    python基础之编码问题   python基础之编码问题 本节内容 字符串编码问题由来 字符串编码解决方案 1.字符串编码问题由来 由于字符串编码是从ascii--->unicode---&g ...

  6. Python的字符编码

    Python的字符编码 1. Python字符编码简介 1. 1  ASCII Python解释器在加载.py文件的代码时,会对内容进行编码,一般默认为ASCII码.ASCII(American St ...

  7. python中的编码与解码

      编码与解码 首先,明确一点,计算机中存储的信息都是二进制的   编码/解码本质上是一种映射(对应关系),比如‘a’用ascii编码则是65,计算机中存储的就是00110101,但是显示的时候不能显 ...

  8. Python常用字符编码(转)

    Python常用字符编码   字符编码的常用种类介绍 第一种:ASCII码 ASCII(American Standard Code for Information Interchange,美国信息交 ...

  9. Python常见字符编码间的转换

    主要内容:     1.Unicode 和 UTF-8的爱恨纠葛     2.字符在硬盘上的存储     3.编码的转换     4.验证编码是否转换正确     5.Python bytes类型 前 ...

  10. python 3字符编码

    python 3字符编码 官方链接:http://legacy.python.org/dev/peps/pep-0263/ 在Python2中默认是ascii编码,Python3是utf-8编码 在p ...

随机推荐

  1. 替换"marquee",实现无缝滚动

    js的marquee标签,可以实现元素循环滚动,但是不能无缝连接,要实现“无缝滚动”的效果必须使用js(借鉴百度),思路是使要滚动元素相对位置不断改变,上下滚动就相对top或者bottom,左右滚动就 ...

  2. SpingBoot之集成Redis集群

    一.安装Redis集群 安装步骤参照网上教程,Mac安装步骤参照https://github.com/muyl/mac-docker-redis-cluster 二.创建SpringBoot工程 创建 ...

  3. 人人都懂区块链--pdf电子版学习资料下载

    人人都懂区块链 21天从区块链“小白”到资深玩家电子版pdf下载 链接:https://pan.baidu.com/s/1TWxYv4TLa2UtTgU-HqLECQ 提取码:6gy0 好的学习资料需 ...

  4. Centos 7环境下修改主机名

    步骤如下: 一.首先把虚拟机打开,用root账户进行登录后打开终端 二.我们看到我们虚拟机名称是默认的主机名. 三.用vi编辑器编辑etc目录下的hostname文件,输入“vi /etc/hostn ...

  5. 搭建Nginx正向代理服务

    需求背景: 前段时间公司因为业务需求需要部署一个正向代理,需要内网服务通过正向代理访问到外网移动端厂商域名通道等效果,之前一直用nginx做四层或者七层的反向代理,正向代理还是第一次配置,配置的过程也 ...

  6. 【MongoDB】2019年MongoDB中文社区广州大会,干货满满的分享活动

    1 介绍 MongoDB中文社区(mongoing.com)是大中华区获得官方认可的中文社区,11月23日下午,在广州举办了线下用户大会,带给大家一手干货和实践. 2 大会议程 大会组织者对时间的把控 ...

  7. 神奇的 SQL 之 MySQL 性能分析神器 → EXPLAIN,SQL 起飞的基石!

    前言 开心一刻 某人养了一头猪,烦了想放生,可是猪认识回家的路,放生几次它都自己回来了.一日,这个人想了个狠办法,开车带着猪转了好多路进山区放生,放生后又各种打转,然后掏出电话给家里人打了个电话,问道 ...

  8. 玩转网络(一)用TTL(Time To Live)排查网络问题

    先大概介绍一下TTL(Time To Live)吧! TTL翻译过来就是网络生存时间,说的是一个网络数据包,它在网络设备中转发的跳数(网络设备这里一般指的是路由器),默认值为64,也有很多设置为了12 ...

  9. PHP变量的初始化以及赋值方式介绍

    什么是变量 变量通俗的来说是一种容器.根据变量类型不同,容器的大小不一样,自然能存放的数据大小也不相同.在变量中存放的数据,我们称之为变量值. PHP 中的变量用一个美元符号后面跟变量名来表示.变量名 ...

  10. 如何配置tomcat的环境变量

    如何配置tomcat的环境变量 安装好tomcat之后, 按照这个操作,计算机→属性→高级系统设置→高级→环境变量,打开环境变量设置框. 以本人的tomcat 8.0为例:安装下来如图 那么我的tom ...