Python乱码九问

简介: Python乱码九问
  • 0 如何查看py源文件编码


  • 1 如何确定py中静态字符串的编码


  • 2 如何查看标准输入和标准输出的编码


  • 2.1 通过Python sys库查看


  • 2.2 查看环境变量LANG


  • 2.3 执行locale


  • 3 如何修改标准输入和标准输出的编码


  • 4 定义字符串时前缀'u'和'b'的区别


  • 5 定义a=u'后端技术小屋'和b=b'后端技术小屋',打印a和b的结果为何相同


  • 6 执行py的标准输出重定向到文件中是什么编码?


  • 7 为何vim打开文件无乱码,但是cat文件有乱码


  • 8 vim打开文件有乱码,但是cat文件无乱码


  • 9 总结



大家可能和我一样,在Python日常开发过程中会遇到各种各样的编码问题。因此在此以个人的踩坑经验总结出一些常见问题和解决方案。




0 如何查看py源文件编码


vim py文件 输入


:set fileencoding


输出


fileencoding=utf-8




1 如何确定py中静态字符串的编码


静态字符串的编码方式取决于文件头中coding的设置。在下面的代码中,变量name以UTF-8编码。


#!/usr/bin/env python
# coding: utf-8
name = "后端技术小屋"


如果不设置coding,运行py文件时便会报语法错误,因为Python Interpreter不识别文件中的中文字符


SyntaxError: Non-ASCII character '\xe5' in file 1.py on line 2, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details




2 如何查看标准输入和标准输出的编码


以下三种方法皆可查看stdin/stdout的编码


2.1 通过Python sys库查看


$ python 
Python 2.7.6 (default, Nov 13 2018, 12:45:42) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.stdin.encoding
UTF-8
>>> print sys.stdout.encoding
UTF-8
>>>


2.2 查看环境变量LANG


$ echo $LANG
en_US.UTF-8


2.3 执行locale


$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US:
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=




3 如何修改标准输入和标准输出的编码


首先我们需要知道是环境变量LANG决定了stdinstdout的编码


如果只是想临时修改,在命令行通过export LANG='XXX'指定标准输入/输出编码即可。当终端退出时该设置即失效。


如果想永久修改:执行vim /etc/sysconfig/i18n, 在其中修改LANG的取值,然后执行source /etc/sysconfig/i18n即可生效。




4 定义字符串时前缀'u'和'b'的区别


首先我们假设py文件头中# coding: utf-8

执行a = u'后端技术小屋'时,会将UTF-8编码的静态字符串转化成Unicode编码,最后赋值给a;


执行b = b'后端技术小屋'时,则直接将UTF-8编码的静态字符串赋值给b



5 定义a=u'后端技术小屋'和b=b'后端技术小屋',打印a和b的结果为何相同


假设py文件头中指定coding为UTF-8,且标准输入/输出的编码为UTF-8


Python执行print a时,会自动将Unicode转化成标准输出的编码格式UTF-8,然后输出


Python执行print b时,字符串b的编码为UTF-8,恰好与标准输出相同。虽然定义a和b时的编码方式不同,但是打印它们时都会转化为标准输出的编码,所以我们看到打印a和b的结果相同。


实际上这里有一些巧合:字符串b的编码恰好与标准输出相同。一旦b的编码和标准输出的编码不一致了(比如b的编码换成了GBK),我们看到的将是乱码,因为GBK编码无法自动转化为UTF-8,而我们在Python开发中遇到的中文乱码问题大部分来源于此。


在实际开发中,强烈建议将可能含有中文的字符串一律转换成Unicode编码之后再打印。如下所示:


# coding: gbk
a = "后端开发小屋"     # GBK编码
aa = a.decode("gbk")  # Unicode编码
print aa


# coding: utf-8
a = "后端开发小屋"        # UTF-8编码
aa = a.decode("utf-8")   # Unicode编码
print aa




6 执行py的标准输出重定向到文件中是什么编码?


编码方式同标准输出




7 为何vim打开文件无乱码,但是cat文件有乱码



说明文件和标准输出编码不一致。而vim支持文件编码,所以vim打开文件无乱码,cat文件有乱码。所以解决思路是使得文件编码与标准输出编码一致,即可消除乱码。


解决方法1: 通过iconv -f XXX -t XXX  file, 将文件转码,使得其编码与标准输出一致

解决方法2: 修改标准输出编码(参考问题2), 使得其与文件编码一致




8 vim打开文件有乱码,但是cat文件无乱码


说明vim不识别此种文件编码


解决方法:


  • vim中输入:set fileencoding, 查看文件编码


  • vim ~/.vimrc, 在set fileencodings列表中加入该文件编码,例如set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1


  • vim重新打开文件




9 总结


说了这么多,总结下:


  • Python开发中,对于可能含有中文的字符串,如需打印,需将其转化为Unicode编码。因为python会自动将unicode转化成输出介质的编码。


  • 标准输出、标准输入、文件、vim(或其他编辑器)上的乱码问题,可根据如上问题举一反三,对症下药加以解决。


相关文章
|
C++ Python Perl
终于解决VScode中python/C++打印中文全是乱码的问题了
终于解决VScode中python/C++打印中文全是乱码的问题了
终于解决VScode中python/C++打印中文全是乱码的问题了
|
数据采集 算法 Linux
Python 抓取网页乱码原因分析
比如,在 windows 的控制台(gbk)里抓取了一个 utf-8 编码的网站。或者,在 Mac / Linux 的终端(utf-8)里抓取了一个 gbk 编码的网站。因为多数网站采用 utf-8 编码,而不少人又是用 windows,所有这种情况相当常见。
|
算法 Python
程序解码错误-由python的requests.post 请求结果乱码引起的思考
最近,在使用python的requests.post的时候,不论结果如何处理,得到的都是乱码。乱码的原因是什么?Accept-Encoding和Content-Encoding的本质是什么?
472 0
python乱码,python编码,python中文编码转换
python乱码,python编码,python中文编码转换
|
JavaScript Python
一日一技:Python写的csv文件,如何让 Excel 双击打开不乱码?
一日一技:Python写的csv文件,如何让 Excel 双击打开不乱码?
249 0
|
Python
Python编程:sublime打开中文文本乱码
Python编程:sublime打开中文文本乱码
132 0
Python编程:sublime打开中文文本乱码
|
数据采集 JSON 中间件
Python爬虫:python2使用scrapy输出unicode乱码
Python爬虫:python2使用scrapy输出unicode乱码
199 0
|
Python
Python mapfinance库②中文标题乱码 与 显示负数 解决方案
Python mapfinance库②中文标题乱码 与 显示负数 解决方案
612 0
Python mapfinance库②中文标题乱码 与 显示负数 解决方案