python在终端上中文乱码问题的小结

时间:2023-02-10 08:07:00

在命令行终端上工作时,经常会碰到一个头疼的问题就是中文乱码。今天对乱码这一块儿的问题做了一个梳理,留作后用,也希望对读者有所帮助。

这里我所理解的牵涉编码的地方一共有五处:

    • Python代码文件前两行声明的编码
    • Python代码文件实际存储所使用的编码
    • Vim的显示编码
    • Linux系统的文件编码
    • SecureCRT等终端设置的显示编码

严格来讲,五码一致的时候,如果文件没有损坏,应该是能够正常显示了。

 

先介绍一些背景知识:

 

一、Python内部编码

字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。

decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码。

encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。

因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode,然后再encode成其他编码

代码中字符串的默认编码与代码文件本身的编码一致。

如果字符串是这样定义:s=u'中文',则该字符串的编码就被指定为unicode了,即python的内部编码,而与代码文件本身的编码无关。因此,对于这种情况做编码转换,只需要直接使用encode方法将其转换成指定编码即可。

(参考链接:http://www.jb51.net/article/17560.htm

 

二、Python编码声明

如果python代码文件中包含中文,就一定要在代码文件的前两行(注意:一定要是前两行)做出编码声明,否则python代码默认采用ASCII保存,这样遇到中文字符就会报错。在代码头部声明编码的方式有三种:

  • # coding=<encoding name>
  • # -*- coding: <encoding name> -*-
  • # vim: set fileencoding=<encoding name>

 

三、Vim中有关编码的选项

在 Vim 中,有四个与编码有关的选项,它们是:fileencodings、fileencoding、encoding 和 termencoding。

encoding 是 Vim 内部使用的字符编码方式。当我们设置了 encoding 之后,Vim 内部所有的 buffer、寄存器、脚本中的字符串等,全都使用这个编码。

termencoding 是 Vim 用于屏幕显示的编码,在显示的时候,Vim 会把内部编码转换为屏幕编码,再用于输出。

当 Vim 从磁盘上读取文件的时候,会对文件的编码进行探测。如果文件的编码方式和 Vim 的内部编码方式不同,Vim 就会对编码进行转换。转换完毕后,Vim 会将 fileencoding 选项设置为文件的编码。当 Vim 存盘的时候,如果 encoding 和fileencoding 不一样,Vim 就会进行编码转换。

编码的自动识别是通过设置fileencodings 实现的,注意是复数形式。fileencodings 是一个用逗号分隔的列表,列表中的每一项是一种编码的名称。当我们打开文件的时候,VIM 按顺序使用 fileencodings 中的编码进行尝试解码,如果成功的话,就使用该编码方式进行解码,并将 fileencoding 设置为这个值,如果失败的话,就继续试验下一个编码。

(参考链接:http://www.cnblogs.com/xuxm2007/archive/2012/07/18/2556653.html

 

四、Linux系统的编码设置

Linux的系统编码设置可以通过设置locale来完成,直接在命令行敲locale,然后回车,即可查看当前系统的编码设置,与保存文件相关的设置是LC_CTYPE。

如LC_CTYPE=zh_CN.gb18030,即把系统的编码设置成为了gb18030。

Locale的详细说明可以参考:http://blog.csdn.net/angelseyes/article/details/4820586

 

 

下面结合一些实例来加深理解:

先看下面两个代码文件:

python在终端上中文乱码问题的小结

左边的文件名为 cp936.py,采用cp936编码,右边文件名为 utf-8.py,采用utf-8编码。


 

下面看看不同的系统编码和终端(secureCRT)编码设置下的情况:(后文有详细附图)

 

终端编码:gb18030

终端编码:UTF-8

系统编码:gb18030

cp936.py

cat

正常

cp936.py

cat

乱码

vim 打开

正常

vim 打开

乱码

print

正常

print

乱码

print decode

正常

print decode

乱码

utf-8.py

cat

乱码

utf-8.py

cat

正常

vim 打开

正常

vim 打开

乱码

print

乱码

print

正常

print decode

正常

print decode

乱码

系统编码:UTF-8

cp936.py

cat

正常

cp936.py

cat

乱码

vim 打开

乱码

vim 打开

正常

print

正常

print

乱码

print decode

乱码

print decode

正常

utf-8.py

cat

乱码

utf-8.py

cat

正常

vim 打开

乱码

vim 打开

正常

print

乱码

print

正常

print decode

乱码

print decode

正常

可以看到左上和右下区中,因为系统编码和终端编码一致,所以绝大部分情况都是正常的,乱码的情况在于文件编码与系统编码不一致,导致不能正常显示。可以使用iconv命令将代码文件的编码转为跟系统一致,这样cat出来或者直接print就不会乱码了。

左下和右上区,因为系统编码和终端编码不一致,所以出现了大范围乱码,所以处理的首选方案是将系统的编码和终端的编码调到一致。当然这时候也有一些方法先让文件正常显示,但是要从根本上解决还是最好将系统编码与终端编码调到一致。

比如右上区,要使vim正常显示文件,只需要 set termencoding=utf-8,即把vim的显示编码调整为跟终端编码一致即可。

要解决print decode的乱码,只需将decode以后的unicode码再encode为终端编码即可正常显示。

要解决cat和直接print的乱码,就需要使用iconv命令将代码文件的编码转为与终端编码一致,就可以正常cat了。

        

附图:

系统编码:gb18030    终端编码:gb18030

python在终端上中文乱码问题的小结

使用vim打开

python在终端上中文乱码问题的小结

 

系统编码:gb18030    终端编码:UTF-8

python在终端上中文乱码问题的小结

使用vim打开

python在终端上中文乱码问题的小结

 

系统编码:UTF-8    终端编码: gb18030

python在终端上中文乱码问题的小结

使用vim打开

python在终端上中文乱码问题的小结

 

系统编码:UTF-8    终端编码: UTF-8

python在终端上中文乱码问题的小结

使用vim打开

python在终端上中文乱码问题的小结