python编码问题

 

编码:真实字符 -->二进制串
解码:二进制串 -->真实字符

 

常见的编码方式:

 

ASCII:1967 年第一次发布。ASCII码占8位,可以表示256个不同的字符。共收录了 128 个字符,包括控制码、空格、标点、数字、大小写字母,这样计算机就可以用不同字节来存储英语的文字了。

 

GB2312:ASCII码的中文扩展。规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样就可以组合出大约7000多个简体汉字。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127号以下的那些就叫”半角”字符了。 
 

GBK:包括了 GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。用上了GB2312 没有用到的码位,并且规定只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。

 

GB18030:在GBK的基础上,增加了几千个新的少数民族的字。

 

GB2312、GBK、GB18030统称为双字节字符集DBCS,Double Byte Charecter Set )在DBCS系列标准里,最大的特点是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里,因此程序为了支持中处理,必须要注意字串里的每一个字节的值,如果这个值是大于127的,就认为一个双字节字符集里的字符出现了。那时候一个汉字算两个英文字符!

 

UNICODE:包括了地球上所有文化、所有字母和符号的编码。用两个字节,也就是16位来统一表示所有的字符,对于ASCII里的“半角”字符,unicode 包持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。

 

UTF-8:是 unicode的一种实现方式。unicode是一种字符集,不属于编码方式,而utf-8是具体实现unicode思想的一种编码。

unicode 在很长一段时间内无法推广,直到互联网的出现,为解决 unicode 在网络上传输的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,而 UTF-16 就是每次16个位。UTF-8就是在互联网上使用最广的一种 unicode 的实现方式,这是为传输而设计的编码,并使编码无国界。UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度,当字符在 ASCII 码的范围时,就用一个字节表示,保留了 ASCII 字符一个字节的编码做为它的一部分。注意的是 unicode 一个中文字符占2个字节,而UTF-8一个中文字符占3个字节。从 unicode 到 uft-8 并不是直接的对应,而是要过一些算法和规则来转换。
 

Unicode是字符集,ASCII, GBK, UTF-8等都是编码方式。

 

python程序的编码问题

 

python2默认ASCII编码,python3是 UTF-8。

不同编码方式的含义是:将这个py文件用什么编码方式转化为二进制文件并存在计算机中。(这句话不知道描述准不准确)

在python2中,如果有非 ASCII 字符,需要在第一行或第二行声明:# -*- coding: utf-8 -*- 或者 #coding=utf-8

作用是:告诉python用什么编码去读取这个.py文件。

 

不同编码之间不能直接转换,需要通过unicode字符集中间过渡下。

其他语言 -> unicode:是一种解码过程,使用decode

unicode -> 其他语言:是编码过程,使用encode

 

# -*- coding: utf-8 -*-

h = '哈哈'               # utf-8
print  h
print 'type:', type(h)
print repr(h)           # repr(string) 可以打印原始字符串

u = h.decode('utf-8')   # decode是将其他编码方式转变为Unicode  
print u
print 'type:', type(u)
print repr(u)

g = u.encode('gbk')     # 将Unicode转变为gbk
print g
print 'type:', type(g)
print repr(g)


# 输出
哈哈
type: 
'\xe5\x93\x88\xe5\x93\x88'。   # utf-8的编码方式,一个汉字占三个字节

哈哈
type: 
u'\u54c8\u54c8'                # Unicode一个汉字占两个字节

????
type: 
'\xb9\xfe\xb9\xfe'             # gbk

 

python2中有两种不同的字符串数据类型,分别为str和unicode(除了Unicode之外,其他所有编码方式的字符串都是str类型)

# -*- coding: utf-8 -*-
  
h = '哈哈'
print h, type(h)

h_unicode = h.decode('utf-8')
print h_unicode, type(h_unicode)

h_gbk = h_unicode.encode('gbk')
print h_gbk, type(h_gbk)

输出
哈哈 
哈哈 
???? 

程序运行时GBK编码没有正确输出,我通过locale命令查看shell的编码方式是UTF-8,而gbk编码不能直接使用utf-8解码。(windows系统好像默认gbk编码,可以正确print gbk的字符串,不能正确print utf字符串。)

解决这个问题有两种方法:

1、修改py文件第一行文件的编码方式,使python和shell编码方式相同(# -*- coding: utf-8/gbk -*-

2、修改中文字符串的编码方式为Unicode或者和shell相同:  

        s = u'哈哈' 或者 s = '哈哈'.decode('utf-8')      # 将中文用Unicode存储。因为utf和gbk不能相互编解码,存为Unicode就可以了

        s = '哈哈'.decode('utf-8').encode('gbk')

 

使用 sys.setdefaultencoding('utf-8') 方法可以更改文件的默认编码方式,通常情况下可以解决python2所有的编码问题,但是可能会引入一些bug:立即停止使用 setdefaultencoding('utf-8'), 以及为什么

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

作用:将Python的编码默认编码方式由ascii码换成了utf-8

 

python2的中文文件读写问题

Windows中默认的文件格式是GBK(gb2312),Linux一般都是UTF-8

查看文件编码方式的方法:

1、在vim中查看文件的编码方式: 

:set fileencoding

如果想查看其它编码格式的文件或者想解决用Vim查看文件乱码的问题有两种方式:

  • 在vim中
:set fileencoding=utf-8  
  • 在 ~/.vimrc 文件中添加以下内容,可以让vim自动识别文件编码(可以自动识别UTF-8或者GBK编码的文件),其实就是依照 fileencodings提供的编码列表尝试,如果没有找到合适的编码,就用latin-1(ASCII)编码打开。
set encoding=utf-8 fileencodings=ucs-bom,utf-8,cp936 

2、enca(sudo yum install -y enca)

$ enca filename

enca对某些GBK编码的文件识别的不是很好,识别时会出现: Unrecognized encoding 

通过enca转换文件编码方式:

enconv -L zh_CN -x UTF-8 filename

 

其他问题

1、input():使用标准输入流,输入的数据编码方式和shell的编码方式相同

2、使用locale查看shell默认的编码方式,会发现不同系统返回的结果可能不同。我本机返回的是zh_CN.UTF-8,服务器返回的是en_US.UTF-8

en_US.UTF-8:你说英语,你在美国,字符集是utf-8 
zh_CN.UTF-8:你说中文,你在中国,字符集是utf-8 
如果LANG环境变量是en_US.UTF-8,那么系统的菜单、程序的工具栏语言、输入法默认语言就都是英文的。 
如果LANG环境变量是zh_CN.UTF-8,那么系统的菜单、程序的工具栏语言、输入法默认语言就都是中文的。

彻底搞懂 python 中文乱码问题

理解和解决Python2中的编码问题

Linux查看文件编码格式及文件编码转换

你可能感兴趣的:(Python)