python 中文乱码问题学习
作者:互联网
python的IDLE编辑代码使用中文,运行程序乱码,对此很苦恼,于是搜索解决方法
彻底搞懂 python 中文乱码问题
中文乱码实例讲解
我们来说说 Python 中是如何存储字符的,先来看一个乱码的例子。新建一个 demo.py 文件,文件存储格式为utf-8
文件中内容如下。
s = "中文"
print s
在 cmd 中运行 python demo.py
,什么,我只是想打印中文
两个字居然给我报错,简直不可理喻啊!
![](https://ask.qcloudimg.com/http-save/6853689/qsvo35rqch.png?imageView2/2/w/1620)
赶紧打开 python 自带的 idle 试试看,一点问题都没有啊,这是为什么呢?
![](https://ask.qcloudimg.com/http-save/6853689/992h72uo76.png?imageView2/2/w/1620)
回头好好看看 cmd 下报的错误Non-ASCII character '\xe4' in file demo.py on line 1, but no encoding declared;
,翻译过来就是 在 demo.py 文件的第 1 行有非 ASCII 字符 ‘\xe4’,而且没有声明编码,从上面基础知识可知,ASCII 编码是不能表示汉字中文的,demo.py 文件第一行有中文两个汉字,而 demo.py 文件存储格式为utf-8
,所以中文两个汉字在文件中存储的时候是以 utf-8
编码存储的,查看 demo.py 文件 16 进制可以看到中文 存储的是 \xe4\xb8\xad\xe6\x96\x87
。
![](https://ask.qcloudimg.com/http-save/6853689/vl6d52pyre.png?imageView2/2/w/1620)
16 进制查看用的是 notepad++ 自带的 HEX-Editor 插件,另外函数 repr
也能显示原始字符串,如下。
# encoding:utf-8
import sys
print sys.getdefaultencoding()
s = "中文"
print repr(s)
![](https://ask.qcloudimg.com/http-save/6853689/ear72da55l.png?imageView2/2/w/1620)
sys.getdefaultencoding()
读取 python 默认编码是 ASCII,而 ASCII 是不认识 \xe4
的,所以会报错Non-ASCII character '\xe4' in file demo.py on line 1, but no encoding declared;
,此时只要在 demo.py 文件头加上 # encoding:utf-8
就可以了,虽然是注释,但 python 看到这句话就知道了接下来应该用utf-8
编码了,而 demo.py 存储时也是utf-8
的,所以就正常了。
# encoding:utf-8
s = "中文"
print s
编码声明注释写成
# -*- coding: utf-8 -*-
也是可以的,只要满足正则表达式^[ \t\v]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)
就OK。
我们再次在 cmd 下运行 python demo.py 试试看。
![](https://ask.qcloudimg.com/http-save/6853689/qd2uy7acuy.png?imageView2/2/w/1620)
啥,啥,啥,说好的显示中文呢?这不是逗我吗?去 python idle 下试试看。
![](https://ask.qcloudimg.com/http-save/6853689/1eeejem1wq.png?imageView2/2/w/1620)
为什么同样的文件在 python idle 中却正常呢?肯定是 cmd 有问题,是的,我也是这样想的,那我试着在 cmd 下进入 python 交互模式输出中文看看,我去居然 cmd 下也是可以正常输出 中文的,相信看到这里小伙伴们都已经晕了。
![](https://ask.qcloudimg.com/http-save/6853689/1687z4nvmo.png?imageView2/2/w/1620)
别急,听我慢慢分析。其实当在 cmd 或者 idle 中打印字符的时候已经和文件编码方式没有关系了,此时起作用的是输出环境也就是 cmd 或者 idle 的编码方式有关,查看 cmd 的编码命令是 chcp
,返回 936,去网上查找可知 936 代表 GBK
编码,这下我们大概知道什么原因了,demo.py 文件存储和编码声明都是utf-8
,但是 cmd 显示编码是 GBK
,而将中文
的utf-8
编码 \xe4\xb8\xad\xe6\x96\x87
强制转换为 GBK
就会乱码了,GBK
是两个字节存储一个中文字符,所以 \xe4\xb8\xad\xe6\x96\x87
会解码成三个字,很不幸这三个字涓枃
不是常用字也不是我们想要的字符,所以就认为是乱码了。为什么在 cmd 下进入 Python 交互式命令行可以呢,这是因为当在 python 交互式命令行输入s = "中文"
时,中文
这两个汉字其实是以 GBK
编码存储的,cmd 默认编码是 GBK
,不信看s
打印\xd6\xd0\xce\xc4
,这就是GBK
编码方式存储,而utf-8
编码方式存储同样的中文
为\xe4\xb8\xad\xe6\x96\x87
。下面告诉大家怎么解决在 cmd 下执行文件正确输出中文问题。
1、demo.py 文件和编码声明都为 GBK
这种方法比较笨,就是把 demo.py 文件改为 GBK
存储,而且编码声明也是GBK
,个人不推荐。
# encoding:gbk
s = "中文"
print s
print repr(s)
![](https://ask.qcloudimg.com/http-save/6853689/k8qtqzwmu8.png?imageView2/2/w/1620)
2、中文用 unicode 表示
只要在中文前面加上个小u
标记,后面的中文就用 unicode
存储了。
# encoding:utf-8
s = u"中文"
print s
print repr(s)
cmd 下是可以打印 unicode 字符的,如下。
![](https://ask.qcloudimg.com/http-save/6853689/i2htlq48fs.png?imageView2/2/w/1620)
3、把中文强制转换为GBK
或者unicode
编码
强制转换为unicode
编码,在 Python 中编码是可以互相转换的,比如从utf-8
转换为gbk
,不同编码之间不能直接转换,需要通过unicode
字符集中间过渡下,从上面基础知识可知unicode
是一种字符集,不属于编码,而utf-8
是具体实现unicode
思想的一种编码。utf-8
转换为unicode
是一种解码过程,通过decode
可从utf-8
解码成unicode
。
# encoding:utf-8
s = "中文"
u = s.decode('utf-8')
print u
print type(u)
print repr(u)
![](https://ask.qcloudimg.com/http-save/6853689/76j1joc6nr.png?imageView2/2/w/1620)
强制转换为gbk
编码,上一步已经从utf-8
转换为unicode
了,从unicode
是编码的过程,通过encode
实现。
# encoding:utf-8
s = "中文"
u = s.decode('utf-8')
g = u.encode('gbk')
print g
print type(g)
print repr(g)
![](https://ask.qcloudimg.com/http-save/6853689/uczffjw9x5.png?imageView2/2/w/1620)
总结 windows cmd 窗口下不支持utf-8
,想要显示中文必须转换为gbk
或者unicode
,而 Python idle 中这三种编码都支持。中文乱码的出现都是由于编码不一致导致的,存储的是用utf-8
,打印的时候用gbk
就会乱码了,所有要保证不乱码尽量保持统一,建议全部使用unicode
。
decode 解码
从其它编码变成unicode
叫解码,解码用的方法是decode
,第一个参数为被解码的字符串原始编码格式,如果写错了也会报错。比如 s 是utf-8
,用gbk
去解码就会报错。
# encoding:utf-8
s = "中文"
u = s.decode('gbk')
print u
print repr(u)
![](https://ask.qcloudimg.com/http-save/6853689/6x1g4aj3wn.png?imageView2/2/w/1620)
小提示 在 Python idle 和 cmd 下直接输入 s = "中文"
会以 gbk
编码的,如果在文件中输入 s = "中文"
且文件存储格式为utf-8
,那么 s 是以utf-8
编码存储的,有点不一样曾经踩过坑,及时 Python idle 成功了文件运行的时候也可能失败。
encode 编码
不可以直接从utf-8
转换为gbk
,必须经过unicode
中间转换,这点很重要,被编码的原始字符串一定要为unicode
,否则会报错。
raw_input
raw_input 是获取用户输入值的,获取到的用户输入值和当前运行环境编码有关,比如 cmd 下默认编码是 gbk
,那么输入的汉字就是以gbk
编码,而不管 demo.py 文件编码格式和编码声明。
# encoding:utf-8
s = raw_input("input something: ")
print s
print type(s)
print repr(s)
![](https://ask.qcloudimg.com/http-save/6853689/wajgwaqnue.png?imageView2/2/w/1620)
GBK 编码一个汉字两个字节,UTF-8 一个汉字通常3个字节。
细心的朋友已经注意了,raw_input
的提示语我用的是英文,那改成中文看看,果真出现乱码了。
# encoding:utf-8
s = raw_input("请输入中文汉字:")
print s
print type(s)
print repr(s)
![](https://ask.qcloudimg.com/http-save/6853689/60dz5oomgk.png?imageView2/2/w/1620)
怎么办呢?把提示字符串强制为gbk
编码就好,unicode
和utf-8
都不可以。
# encoding:utf-8
s = raw_input(u"请输入中文汉字:".encode('gbk'))
print s
print type(s)
print repr(s)
![](https://ask.qcloudimg.com/http-save/6853689/zx557i8dha.png?imageView2/2/w/1620)
相等陷阱
“中文”这两个字符串用不同的编码存储是不一样的,utf-8
编码和gbk
编码存储的“中文”都不一样。
![](https://ask.qcloudimg.com/http-save/6853689/hr0wtf7pii.png?imageView2/2/w/1620)
总结
一口气说了这么多,不知道你们看懂没?想要不乱码,记住以下5点法则就好。
- 文件存储为
utf-8
格式,编码声明为utf-8
,# encoding:utf-8
- 出现汉字的地方前面加
u
- 不同编码之间不能直接转换,要经过
unicode
中间跳转 - cmd 下不支持
utf-8
编码 raw_input
提示字符串只能为gbk
编码
标签:编码,中文,utf,python,cmd,乱码,unicode,print 来源: https://www.cnblogs.com/merlin-lan/p/16425636.html