python 中文乱码问题学习

python的IDLE编辑代码使用中文,运行程序乱码,对此很苦恼,于是搜索解决方法

彻底搞懂 python 中文乱码问题

 以下都是针对python2而言

中文乱码实例讲解

我们来说说 Python 中是如何存储字符的,先来看一个乱码的例子。新建一个 demo.py 文件,文件存储格式为utf-8文件中内容如下。

s = "中文"
print s

在 cmd 中运行 python demo.py,什么,我只是想打印中文两个字居然给我报错,简直不可理喻啊!

赶紧打开 python 自带的 idle 试试看,一点问题都没有啊,这是为什么呢?

回头好好看看 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

16 进制查看用的是 notepad++ 自带的 HEX-Editor 插件,另外函数 repr也能显示原始字符串,如下。

# encoding:utf-8
import sys
print sys.getdefaultencoding()
s = "中文"
print repr(s)

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 试试看。

啥,啥,啥,说好的显示中文呢?这不是逗我吗?去 python idle 下试试看。

为什么同样的文件在 python idle 中却正常呢?肯定是 cmd 有问题,是的,我也是这样想的,那我试着在 cmd 下进入 python 交互模式输出中文看看,我去居然 cmd 下也是可以正常输出 中文的,相信看到这里小伙伴们都已经晕了。

别急,听我慢慢分析。其实当在 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)

2、中文用 unicode 表示

只要在中文前面加上个小u标记,后面的中文就用 unicode 存储了。

# encoding:utf-8
s = u"中文"
print s
print repr(s)

cmd 下是可以打印 unicode 字符的,如下。

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)

强制转换为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)

总结 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)

小提示 在 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)

GBK 编码一个汉字两个字节,UTF-8 一个汉字通常3个字节。

细心的朋友已经注意了,raw_input的提示语我用的是英文,那改成中文看看,果真出现乱码了。

# encoding:utf-8
s = raw_input("请输入中文汉字:")
print s
print type(s)
print repr(s)

怎么办呢?把提示字符串强制为gbk编码就好,unicodeutf-8都不可以。

# encoding:utf-8
s = raw_input(u"请输入中文汉字:".encode('gbk'))
print s
print type(s)
print repr(s)

相等陷阱

“中文”这两个字符串用不同的编码存储是不一样的,utf-8编码和gbk编码存储的“中文”都不一样。

总结

一口气说了这么多,不知道你们看懂没?想要不乱码,记住以下5点法则就好。

  1. 文件存储为utf-8格式,编码声明为utf-8# encoding:utf-8
  2. 出现汉字的地方前面加 u
  3. 不同编码之间不能直接转换,要经过unicode中间跳转
  4. cmd 下不支持utf-8编码
  5. raw_input提示字符串只能为gbk编码
posted @ 2022-07-27 10:22  mink007  阅读(5462)  评论(0编辑  收藏  举报