美文网首页
python编码问题

python编码问题

作者: Fengya | 来源:发表于2017-03-09 15:33 被阅读132次

阅读python源代码的时候不难发现许多文件开头都有这样一行内容:

# -*- coding: UTF-8 -*-

如果想在python中使用中文,这样的一行声明也是必须的。python中的编码在实际使用的时候也是经常让人感觉很混乱。以下详细研究一下python的编码问题。

来源

python在上世纪九十年代研发发布,那时候研发者很显然没有想到语言有严重的编码问题。因此在python3之前,python编码默认使用的是ascii。因此使用python自带的str的时候,实际上我们用的是默认的ascii编码方式。

使用# -*- coding: UTF-8 -*-这段代码用于声明代码中文本的编码是utf-8。告诉解释器将文件中的文本视为utf-8编码的字符串。当然使用的时候应该保证代码文件确实是以utf-8的形式存储的。

查看python的默认编码方式可以使用以下语句:

import sys
sys.getdefaultencoding()

python2默认使用的是asciipython3使用的是utf-8

扩展

编码发展历程

由于计算机首先在美国出现,编码最开始只需要表达出英文即可。因此首先出现的编码由8位组成一个字符。有256种状态。其中0到32表示特殊用途的字符,比如回车,响铃等等,用于控制当时的机器的行为。之后是空格标点数字字母等等。一直到127号。这个方案叫做ANSIascii(American Standard Code for Information Interchange)编码。

之后由于世界各地开始使用计算机,很多字符无法使用acsii表示,因此开始采用127号之后的状态表示字符。这些字符被称为扩展字符集

对于中国来说,由于没有足够的字节状态表示汉字,所以取消了之前127号之后的扩展字符集,用两个字节来表示汉字。当一个字节小于127的时候,还是表示之前的ascii字符,当大于127的时候,两个字节在一起表示一个中文字符。前面一个字节(高字节)范围是0xA10xF7,后面一个字节(低字节)范围是0xA10xFE。这些多出来的组合用来表示简体汉字外,还将之前的数学符号,罗马希腊字母,日文假名以及之前的acsii中的内容都编制进去了。这些两位字节的字符叫做全角字符,原来的127号以下的字符叫做半角字符。这个汉字方案叫做GB2312

之后,由于中国汉字太多,GB2312方案也已经不够用来表示所有的汉字。所以不仅将之前没有用完的码位拿出来用上,还取消了低字节一定是127号之后的规定。只要第一个字节是大于127号的就表示这是一个汉字的开始。这个扩展之后的编码方案称为GBK标准。GBK标准增加了包括繁体字等等近20000个新的汉字和符号。

接下来,由于需要加入少数民族的文字,这个标准再次扩充,新加入了几千个少数民族文字,扩展成了GB18030

之前的这一系列汉字标准被称作DBCS(Double Byte Character Set)双字节字符集。在DBCS系列标准里,双字节长的汉字字符和单字节的英文字符并存,因此计算字符串的长度的时候一个汉字等于两个英文字符。

以上是中国的编码标准。由于之前没个国家都按照这个过程制定了一套自己的标准,因此这些编码互相不能相通,甚至台湾也使用了自己的一套DBCS系统GIG5。所以ISO(国际标准化组织)提出了一种新的方案。废除了所有的地区性编码方案。制定了一套包含地球上所有文化字幕和符号的编码,Universal Multiple-Octet Coded Character Set,简称UCS,俗称unicode

这时由于储存器空间的极大发展,因此空间不再成为问题了。ISO规定unicode必须使用两个字节16位来表示所有的字符。之前acsii里面的字符,也只是原编码不变,扩展为16位。因此这种方案会在保存英文文本的时候浪费一半的空间。此时,一个汉字和一个英文都是一个字符,不再像之前一样一个汉字是两个英文字符了。一个字符就是两个字节。

但是unicode有很大的缺点。之前提到的字节浪费就是其中之一。另外当不知道编码方式的时候也很难区分acsii码和unicode码。

直到互联网的出现。由于网络传输再一次对编码精炼程度要求很大,为了解决unicode在网上的传输问题,制定了许多UTF(UCS Transfer Format)标准。其中之前提到的utf-8就是每次传输8个位,utf-16就是每次传输16个位。utf-8时网络上使用最广的unicode传输实现方式。utf-8的特点在于它是一种变长的编码方式。使用一到四个字节表示一个符号,根据不同的符号变化字节长度。当字节在ascii范围内的时候,用一个字节表示,这样就解决了英文的存储浪费和无法区分asciiunicode的问题。对于中文来说unicode中中文一个字节,utf-8中一个中文三个字节。从unicodeutf-8需要经过一系列算法和规则。

python中字符串的编码

之前解释了python明文表示使用utf-8来读取文件的作用。这只是解决了python代码读取的问题。python本身的字符串使用也相当混乱(对于3之前)。由于python使用acsii作为编码方式,因此代码里面的字符串默认的格式是ascii。这样在包含中文等字符的操作的时候,由于编码问题就会报错。python3默认的编码方式已经变成了utf-8所以不会有这些问题。以下都是针对python2来说。

python中的字符串有两种,编码之前的unicode和编码过后的str类型。unicode即字面上的编码方式,使用unicode,按照上文说的,中文两个字节。str可以使用不同的编码方式,比如asciigbkutf-8等等。默认使用的是ascii码。

在上面两种模式中,unicode作为在str的各种编码类型之间转换的中间码形式存在。要想在不同的编码之间互相转化,需要先转化成unicode,之后在转化成目的编码。例如:

testStr = "hello"
print type(testStr)                 
# <type 'str'>
print type(testStr.decode("ascii")) 
# <type 'unicode'>
print type(testStr.decode('ascii').encode('utf-8'))
# <type 'str'>

以上过程即将一个ascii编码的字符串转化成unicode又转化成了utf-8。当然,对于hello这串西文字符来说,这两种编码方式没有区别。

虽然如问题中的声明方式可以将代码文件中的编码方式确定为utf-8。但是代码中涉及到文件处理,网络流处理的时候,还需要进行适当的编码转化。Python试图进行隐式的的转化,使用之前提到的默认编码进行字节串和unicode之间的转化。在默认的编码方式是ascii的情况下,大部分这种转化是错误的。这时候会报这样的错误:

a = '你好'
print a.decode()
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
# 用ascii解码汉字报错
print a.decode('utf-8')
# u'\u4f60\u597d'
print a.decode('utf-8').encode()
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
# 用ascii编码汉字报错
print a.decode('utf-8').encode('utf-8')
# 你好

因此,在使用python2的时候,在编码方面要注意尽量使用unicode来进行字符串的操作。字符串需要使用正确的编码标准来进行解码和编码。从外界读取的字符串都先解码成unicode再进行操作,然后输出的时候再编码。

相关文章

  • python 编码问题总结记录

    Python2的默认编码ASCII,这是python编码问题的根本原因,可以想象,python3的编码问题肯定没有...

  • Python优秀博客笔记汇总(持续更新)

    还在烦编码问题? Python 编码错误的本质原因 Python 编码为什么那么蛋疼? Python3 是如何解决...

  • learning

    python在终端进行文件的运行在终端输入 python test.py 时间时间的转换 编码python编码问题

  • Python程序的中文在cmd中乱码问题

    刚开始学python遇到的问题,编码的问题。程序编码是UTF-8,cmd默认是GBK编码

  • 学习资料

    简明python教程Python2字符编码问题小结stackoverflow about python

  • 【python报错】UnicodeDecodeError: &#

    一、问题 二、原因 编码问题:整个Python文件的编码以及文件读取的编码 三、解决方案 1、编码设置 第一行没有...

  • python 编码问题

    以前python2.x版本的编码问题较多,所以这里只针对python3.x版本的问题进行讨论。 Unicode 编...

  • python编码问题

    1. python2中关于utf-8编码问题解决方法: 或者开头加# -*- coding: utf-8 -*-但...

  • Python编码问题

    默认编码 字符串 python2 文本字符串默认编码是ASCII,中文默认UTF-8python3 文本字符串默认...

  • python 编码问题

    1、一些概念 比特 / bit:计算机中最小的数据单位,是单个的二进制数值 0 或 1 字节 / byte:计算机...

网友评论

      本文标题:python编码问题

      本文链接:https://www.haomeiwen.com/subject/usajmttx.html