python 乱码 无效_python显示乱码

本文深入探讨Python编码问题,总结了Python编码相关的概念,如字节流、Unicode对象和终端编码。强调了Python源文件的编码声明、locale与终端编码的一致性对`print`输出的影响,以及`sys.setdefaultencoding()`的作用。通过多个示例解释了如何在不同编码环境下正确处理和打印中文字符。
摘要由CSDN通过智能技术生成

展开全部

多次被python的编码/乱码问题困扰,相信pythoner们都被困扰过,网上铺62616964757a686964616fe78988e69d8331333365646361天盖地的资料太多也参差不齐,就整理了下。本文从使用的角度系统总结了python编码相关的一些概念,将本文的例子玩一遍,基本上对python的编码问题就清楚了。

首先明确几个概念:

字节流:以utf8/gbk等编码编码的字节流。

unicode对象:python代码中,a=u'中国', 或者a='中国'.decode()的结果。

terminal用于显示字符的编码:将一个用utf8/gbk编码的字节流通过terminal指定的编码,去查找对应的字符显示出来。

locale:linux下,Locale 是软件在运行时的语言环境, 它包括语言(Language), 地域 (Territory) 和字符集(Codeset)。一个locale的书写格式为: 语言[_地域[.字符集]]. 所以说呢,locale总是和一定的字符集相联系的。比如:zh_CN.GB2312

编码转换原则:unicode是”中介”,任何编码之间转换都需要先decode()到unicode。

针对python,先把结论放在前面,三点:

#coding:utf-8 #.py文件是什么编码就需要告诉python用什么编码去读取这个.py文件。

sys.stdout.encoding,默认就是locale的编码,print会用sys.stdout.encoding去encode()成字节流,交给terminal显示。所以locale需要与terminal一致,才能正确print打印出中文。

sys.setdefaultencoding(‘utf8’),用于指定str.encode() str.decode()的默认编码,默认是ascii。

对编码字符串a,代码中可以直接写a.encode(“gbk”),但事实上内部自动先通过defaultencoding 去decode成unicode之后再encode()的。

str(xxx)应该也是用这个去编码的。

'ascii' codec can't encode characters in position 7-8: ordinal not in range(128)print的时候出现这个错误一般可以使用这个方案去处理。

为了避免代码中到处都要去encode(“xxx”),还有可能不同的地方写得不一样带来不一致的情况,推荐使用这个:

import sys

reload(sys)

sys.setdefaultencoding('utf8')

例子1:

在python中,unicode vs 字节流:字节流可以从unicode encode得到,unicode可以从utf8/gbk等编码的字节流decode得到。

分析下面这段代码,终端/locale分别为不同编码的情况:

#coding:utf-8 #由于.py文件是utf-8的,所以必须有这一句

import sys

import locale

import os

import codecs

reload(sys)

print sys.getdefaultencoding() + " - sys.getdefaultencoding()"

sys.setdefaultencoding('utf8') #影响encode()

print sys.getdefaultencoding() + " - sys.getdefaultencoding()"

print sys.stdout.encoding + " - sys.stdout.encoding:"

#sys.stdout = codecs.getwriter('utf8')(sys.stdout) #影响print

print sys.stdout.encoding + " - sys.stdout.encoding:"

u = u'中国'

print u + " - u"

a = '中国'

print a + " - a"

print a.decode('utf-8') + " - a.decode('utf-8')"

print a.decode('utf-8').encode('gbk') + " - a.decode('utf-8').encode('gbk')"

print a.decode('utf-8').encode('utf-8') + " - a.decode('utf-8').encode('utf-8')"

print a.decode('utf-8').encode() + " - a.decode('utf-8').encode()"

print (sys.stdout.encoding) + " - (sys.stdout.encoding)"

print (sys.stdout.isatty())

print (locale.getpreferredencoding())

print (sys.getfilesystemencoding())

—终端为UTF-8,locale为zh_CN.GBK—————–

ascii - sys.getdefaultencoding()

utf8 - sys.getdefaultencoding()

GBK - sys.stdout.encoding:

GBK - sys.stdout.encoding:

?й? - u

中国 - a

?й? - a.decode('utf-8')

?й? - a.decode('utf-8').encode('gbk')

中国 - a.decode('utf-8').encode('utf-8')

中国 - a.decode('utf-8').encode()

GBK - (sys.stdout.encoding)

True

GBK

utf-8

—终端为UTF-8,locale为zh_CN.UTF-8—————–

ascii - sys.getdefaultencoding()

utf8 - sys.getdefaultencoding()

UTF-8 - sys.stdout.encoding:

UTF-8 - sys.stdout.encoding:

中国 - u

中国 - a

中国 - a.decode('utf-8')

?й? - a.decode('utf-8').encode('gbk')

中国 - a.decode('utf-8').encode('utf-8')

中国 - a.decode('utf-8').encode()

UTF-8 - (sys.stdout.encoding)

True

UTF-8

utf-8

—终端为GBK,locale为zh_CN.GBK—————–

ascii - sys.getdefaultencoding()

utf8 - sys.getdefaultencoding()

GBK - sys.stdout.encoding:

GBK - sys.stdout.encoding:

中国 - u

涓???? - a

中国 - a.decode('utf-8')

中国 - a.decode('utf-8').encode('gbk')

涓???? - a.decode('utf-8').encode('utf-8')

涓???? - a.decode('utf-8').encode()

GBK - (sys.stdout.encoding)

True

GBK

utf-8

—终端为GBK,locale为zh_CN.UTF-8—————–

ascii - sys.getdefaultencoding()

utf8 - sys.getdefaultencoding()

UTF-8 - sys.stdout.encoding:

UTF-8 - sys.stdout.encoding:

涓???? - u

涓???? - a

涓???? - a.decode('utf-8')

中国 - a.decode('utf-8').encode('gbk')

涓???? - a.decode('utf-8').encode('utf-8')

涓???? - a.decode('utf-8').encode()

UTF-8 - (sys.stdout.encoding)

True

UTF-8

utf-8

例子1总结,对print而言:

unicode的数据如果要显示正常,必须终端与locale一致。sys.stdout.encoding这个值应该来自locale,print会以sys.stdout.encoding去encode并输出到字节流。

encode为终端编码的字节流就能显示正常,无论locale是啥。

最终是terminal通过terminal配置的编码规则去解码成对应的字符并显示出来。

例子2:

关于sys.setdefaultencoding(‘utf8’)的例子:

#coding:utf-8

import sys

reload(sys)

sys.setdefaultencoding('utf8')

print sys.getdefaultencoding() + " - sys.getdefaultencoding()"

a = '中国'

print a + " - a"

print a.encode("gbk") #并不是直接从utf8的字节流转化到gbk的,而是通过defaultencoding decode之后才转的。

print a.decode() #使用默认的defaultencoding

print a.encode() #使用默认的defaultencoding

关于str()和repr()

str()是对各种类型转化成str,如果本来是encoded字符串,则不变,如果为unicode,会encode()

repr()对字符串是将字节流出二进制的值以16进制转化为可见字符。

测试环境locale为GBK

#coding:utf-8

import sys

reload(sys)

sys.setdefaultencoding("utf-8")

a = u'中国'

print a

print str(a)

print repr(a)

print repr(a.encode("utf-8"))

print repr(a.encode("gbk"))

中国

涓????

u'\u4e2d\u56fd'

'\xe4\xb8\xad\xe5\x9b\xbd'

'\xd6\xd0\xb9\xfa'

再深挖下去,还有repr()和eval()的关系,就不深挖了。

关于终端和服务器的编码

另外补充一些关于终端和服务器编码的结论:

1. 对mac iterm2,如果server的locale与mac本地终端的locale一致,才能保证server端与本地的表现一致。

2. cat a.py #就把文件显示出来,就是给terminal一串字节流。terminal根据设置的终端编码规则来显示字符。所以只要文件编码与terminal一致即可,与locale无关。

3. cat a.txt > b.txt #无论locale怎么样,只跟a.txt原来的编码相关

4. echo “中国年过” > a.txt #这个情况下,只有terminal与locale的编码一致,你才能在终端shell打出正确的中文~~~所以a.txt与两者都会一致

追问

=-= 我不是很看得懂,能不能稍微简单一些的告诉我错在哪里,怎么改正

本回答由网友推荐

已赞过

已踩过<

你对这个回答的评价是?

评论

收起

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值