解决python的中文字符编码问题
博客搬家,新博客地址
:https://imlogm.github.io/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/character-encoding/
摘要:最近在做自然语言处理相关的项目,发现中文编码的问题实在需要好好学习下,我用python为例,简单介绍下python编程时如何处理好中文编码的问题。
关键字:自然语言处理, 字符编码, python
1. 从字符编码谈起
讲真,字符编码是很大的一块内容,单用一篇博客是完全讲不完的。这里借用一下大佬的文章:字符编码笔记:ASCII,Unicode 和 UTF-8 - 阮一峰的日志
看完上面的那篇文章之后,相信你对字符编码有了一定的认识。在中文的自然语言处理中,最常遇到的是ASCII,Unicode,UTF-8,GB2312,GBK等。这几种编码,你都可以搜索相关的文章看下,我这里就不展开介绍了。直接用几个python的程序解释下如何在python中处理字符编码的问题。
2. 关于python的str类型和print过程
比如一段程序:
# -*- coding:utf-8 -*- s = "这是一段中文" # s是str类型的变量 print(s) # 程序输出:“这是一段中文”
这段程序中的变量s就是str类型的。我们都知道计算机内部都是二进制的0和1,str类型就是这样的0和1组成的二进制字节流,也就是说这里的变量s在计算机内部是一段二进制字节,并不是字符串。
如果你是在python的交互式编程环境中,那么你可以做个实验:
>>> s = "这是一段中文" >>> s \xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe6\xae\xb5\xe4\xb8\xad\xe6\x96\x87
\x表示这个数是十六进制数,
\xe8表示这个数是十六进制数“E8”,转换为二进制为
11101000,上面的“\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe6\xae\xb5\xe4\xb8\xad\xe6\x96\x87”就是变量s所代表的字节流,换句话说,就是字符串“这是一段中文”在utf-8编码格式下的二进制表示。
这里就出现了两个问题:
- 变量s赋值时,一段中文字符串是怎么变成二进制字节流的?
- 打印变量s时,二进制字节流是怎么变成一段中文字符串的?
首先是问题1。变量s赋值时,字符串经过某种编码方式编码(encode)成为二进制字节,再赋值给变量s。这里的“某种编码方式”由代码显式指出,代码的第一行
# -*- coding:utf-8 -*-就是用来显式地告诉计算机,你在str类型赋值时,用utf-8的编码方式。
然后是问题2。打印变量s时,二进制字节流通过某种编码方式解码(decode)为字符串。这里的“某种编码方式”由操作系统指出。我用的ubuntu系统使用的是utf-8的编码方式。
注意体会
编码和
解码这两个词的不同。编码方式和解码方式一样,才能正常print,否则显示的是乱码。
可能你还是不太明白,我们用上面的程序再做一组实验。因为每台电脑的命令行的编码方式不一样,我用的是ubuntu的系统,编码格式是utf-8,我以我的电脑为例来讲解。同时,注意实验要在命令行的状态下进行。有些ide比较智能,会自动更换输出环境的编码格式,达不到实验效果。
第一个程序和上面的一样,我们来看下效果:
# -*- coding:utf-8 -*- # 命令行的编码方式为utf-8 s = "这是一段中文" # s是str类型的变量,计算机把字符串以utf-8格式编码成二进制字节,赋值给s print(s) # s是str类型的变量,计算机读取s(也就是读取出二进制字节),然后以utf-8格式解码为字符串 # 程序输出:“这是一段中文”
然后,我们改动第一行:
# -*- coding:GBK -*- # 命令行的编码方式为utf-8 s = "这是一段中文" # s是str类型的变量,计算机把字符串以GBK格式编码成二进制字节,赋值给s print(s) # s是str类型的变量,计算机读取s(也就是读取出二进制字节),然后以utf-8格式解码为字符串 # 程序输出:一段乱码
我们再做第三个实验:
# -*- coding:utf-8 -*- # 命令行的编码方式为GBK s = "这是一段中文" # s是str类型的变量,计算机把字符串以utf-8格式编码成二进制字节,赋值给s print(s) # s是str类型的变量,计算机读取s(也就是读取出二进制字节),然后以GBK格式解码为字符串 # 程序输出:一段乱码
我想你应该能理解这三个程序之间的区别。
2. 关于unicode类型
unicode类型是python中的一种字符串类型,在计算机内也是二进制字节。不过不同于str是单纯的二进制字节,unicode类型特指由ucs2或者ucs4编码格式编码的二进制字节。
如果你在python的交互式编程环境中,你可以做个实验:
>>> s = u"这是一段中文" # 这边多了个u,表示变量s为unicode变量 >>> s u'\u8fd9\u662f\u4e00\u6bb5\u4e2d\u6587'
可以看到,和上面str类型的实验结果的
\x不一样了,这里出现的是
\u。
\u代表了在unicode编码表中的位置,比如
\u8fd9就代表unicode编码表中8fd9这个位置的字符。
python中unicode类型的变量是作为一个中转站存在的。比如你要把一段字符串从utf-8编码转为GBK编码,你需要做的是:
# -*- coding:utf-8 -*- s = "这是一段中文" # s是str类型的变量,计算机把字符串以utf-8格式编码成二进制字节,赋值给s s.decode("utf-8") # 二进制字节s以utf-8格式解码到unicode,解码后s从str类型变为unicode类型 s.encode("GBK") # unicode类型的变量s被以GBK格式编码为二进制字符串,编码后变量s从unicode类型变为str类型 # 程序输出:一段乱码
反过来,要把一个GBK编码的字符串转为utf-8也一样,要以unicode作为中转站。
3. sys.setdefaultencoding(‘utf-8’)
网上一些教程会教你,在遇到中文编码问题的时候,在代码的开头加上这几句:
# -*- coding:utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8')
你一试,还真的解决了问题,但你不知道这几句话有什么用。
第一句
# -*- coding:utf-8 -*-上一段已经说了,是为了显式地说明代码是由utf-8格式编码的,如果你不加的话,一般来说是采用默认编码ascii。ascii不支持中文,你的代码中有任何中文就会出错。
后面三句,最重要的是
sys.setdefaultencoding('utf-8'),它的目的是修改默认的解码方式为utf-8。
看下面的实验:
# -*- coding: utf-8 -*- s = '中文字符' # s是字符串经过utf-8编码格式编码后的二进制字节,str类型 s.encode('GBK') # s是二进制字节,它不会直接encode。python会首先调用decode,将s从str类型变为unicode格式,再用GBK编码为str类型
你可以使用以下代码获取python默认的解码方式:
import sys print(sys.getdefaultencoding())
假如你获取到的默认解码方式为ascii。那么:
# -*- coding: utf-8 -*- s = "这是一段中文" # s是字符串经过utf-8编码格式编码后的二进制字节,str类型 s.encode("GBK") # s是二进制字节,它不会直接encode。python会首先调用decode,将s从str类型变为unicode格式,再用GBK编码为str类型 # 如果你的默认解码方式为ascii,那么上面一句话在实际执行时,相当于下面这句话 s.decode("ascii").encode("GBK")
显然,程序会报错:UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe4 in position 。
解决方法1,显示地指明解码格式:
# -*- coding: utf-8 -*- s = "这是一段中文" s.decode("utf-8").encode("GBK")
解决方法2,修改默认解码方式:
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') s = "这是一段中文" s.encode("GBK")
你应该能从这几个实验中明白
sys.setdefaultencoding('utf-8')的作用。
4. 检验学习成果
看看上面链接的博客里所列举的几个错误示例,现在你是否能够一眼就找出错误点,并给出解决方法呢?
阅读更多- 【Todo】Python中文及Java中文问题及解决方法总结 & 及各种字符编码问题跟踪贴
- 关于python中文乱码的一些问题和解决办法
- 【爬虫】python解决QQ邮箱查询接口的中文编码问题
- python中文字符编码decode,encode以及乱码解决总结
- Python输出中文到文件时的字符编码问题
- 解决python3输出中文的问题
- python读取\t\n的文件转换成html表格发送邮件(解决中文乱码问题)
- python程序中文输出问题怎么解决?
- 布同 Python中文问题解决方法(总结了多位前人经验,初学者必看)
- sqlite3 jdbc、c接口、python接口处理中文时遇到的问题及其解决方法
- Python解决中文乱码问题
- 解决python中文乱码问题
- 中文乱码问题 ? 原因:JSP中默认使用iso-8859-1字符编码方式,不支持中文 ? 常见的支持中文的编码方式:gb2312(常用简体汉字)、gbk(简体和繁体汉字)、utf-8 ? 解决中文乱码
- 解决python27 matplotlib 中文不显示问题
- 解决python3 网络请求路径包含中文的问题
- python绘图基础—解决图例中文乱码和负数坐标问题问题
- Python 写入CSV文件时的中文字符编码问题
- python 2: 解决python中的plot函数的图例legend不能显示中文问题
- Python连接MySQL中有关中文乱码的解决问题
- 解决python中文编码混乱的问题