前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >彻底搞懂 python 中文乱码问题

彻底搞懂 python 中文乱码问题

作者头像
py3study
发布2020-01-07 17:05:46
10.7K0
发布2020-01-07 17:05:46
举报
文章被收录于专栏:python3python3

中文乱码实例讲解

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

代码语言:javascript
复制
s = "中文"
print s

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

CMD错误
CMD错误

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

python idle 正确
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 进制存储
16 进制存储

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

代码语言:javascript
复制
# encoding:utf-8
import sys
print sys.getdefaultencoding()
s = "中文"
print repr(s)
repr
repr

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的,所以就正常了。

代码语言:javascript
复制
# encoding:utf-8
s = "中文"
print s

编码声明注释写成# -*- coding: utf-8 -*-也是可以的,只要满足正则表达式^[ \t\v]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)就OK。

我们再次在 cmd 下运行 python demo.py 试试看。

cmd 中文乱码
cmd 中文乱码

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

python idle 正常
python idle 正常

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

cmd 正常
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,个人不推荐。

代码语言:javascript
复制
# encoding:gbk
s = "中文"
print s
print repr(s)
GBK
GBK

2、中文用 unicode 表示

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

代码语言:javascript
复制
# encoding:utf-8
s = u"中文"
print s
print repr(s)

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

unicode
unicode

3、把中文强制转换为GBK或者unicode编码

强制转换为unicode编码,在 Python 中编码是可以互相转换的,比如从utf-8转换为gbk,不同编码之间不能直接转换,需要通过unicode字符集中间过渡下,从上面基础知识可知unicode是一种字符集,不属于编码,而utf-8是具体实现unicode思想的一种编码。utf-8转换为unicode是一种解码过程,通过decode可从utf-8解码成unicode

代码语言:javascript
复制
# encoding:utf-8
s = "中文"
u = s.decode('utf-8')
print u
print type(u)
print repr(u)
unicode
unicode

强制转换为gbk编码,上一步已经从utf-8转换为unicode了,从unicode是编码的过程,通过encode实现。

代码语言:javascript
复制
# encoding:utf-8
s = "中文"
u = s.decode('utf-8')
g = u.encode('gbk')
print g
print type(g)
print repr(g)
gbk
gbk

总结 windows cmd 窗口下不支持utf-8,想要显示中文必须转换为gbk或者unicode,而 Python idle 中这三种编码都支持。中文乱码的出现都是由于编码不一致导致的,存储的是用utf-8,打印的时候用gbk就会乱码了,所有要保证不乱码尽量保持统一,建议全部使用unicode

decode 解码

从其它编码变成unicode叫解码,解码用的方法是decode,第一个参数为被解码的字符串原始编码格式,如果写错了也会报错。比如 s 是utf-8,用gbk去解码就会报错。

代码语言:javascript
复制
# encoding:utf-8
s = "中文"
u = s.decode('gbk')
print u
print repr(u)
decode 报错
decode 报错

小提示 在 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 文件编码格式和编码声明。

代码语言:javascript
复制
# encoding:utf-8
s = raw_input("input something: ")
print s
print type(s)
print repr(s)
gbk
gbk

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

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

代码语言:javascript
复制
# encoding:utf-8
s = raw_input("请输入中文汉字:")
print s
print type(s)
print repr(s)
raw_input 乱码
raw_input 乱码

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

代码语言:javascript
复制
# encoding:utf-8
s = raw_input(u"请输入中文汉字:".encode('gbk'))
print s
print type(s)
print repr(s)
raw_input 正常
raw_input 正常

相等陷阱

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

不相等
不相等

总结

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

  1. 文件存储为utf-8格式,编码声明为utf-8# encoding:utf-8
  2. 出现汉字的地方前面加 u
  3. 不同编码之间不能直接转换,要经过unicode中间跳转
  4. cmd 下不支持utf-8编码
  5. raw_input提示字符串只能为gbk编码
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 中文乱码实例讲解
    • 1、demo.py 文件和编码声明都为 GBK
      • 2、中文用 unicode 表示
        • 3、把中文强制转换为GBK或者unicode编码
          • decode 解码
            • encode 编码
              • raw_input
                • 相等陷阱
                • 总结
                相关产品与服务
                命令行工具
                腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档