广告
返回顶部
首页 > 资讯 > 后端开发 > Python >python编码的意义
  • 781
分享到

python编码的意义

意义python 2023-01-31 07:01:03 781人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

编码,还是编码! python2的直钩——编码异常 当你用Python打开一篇中文文档,准备读取里面的数据开始实验...当你处理好你的数据,打算打印出易于阅读的结果给boss检查...甚至当你刚刚开始编写自己的代码,就写了一句话... t

编码,还是编码!

python2的直钩——编码异常

当你用Python打开一篇中文文档,准备读取里面的数据开始实验...
当你处理好你的数据,打算打印出易于阅读的结果给boss检查...
甚至当你刚刚开始编写自己的代码,就写了一句话...

text = '什么鬼'

只要你开始运行自己的代码,信心满满期待搞定回寝时

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

以及

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

于是你10点前回到寝室以及之后的一系列计划全部泡汤了,垂头丧气的坐下来,你看到两个动词格外亮眼——decodeencode。而他们的中文释义,就是python2对新手的最大陷阱——编码

当我们谈论编码时我们在谈论什么

python中有关编码问题的对象有basestring, str, unicode, 标准库有codecs等,在这篇文章里我们基本上不会提到标准库,而仅仅简单的对对象们进行分析。因为这就够了!

事实上,我们常犯的编码问题,从抛出异常的角度来说分为两种,很明显,本文一开头也列出这两种异常的打印情形,它们分别是

  • py文件编译时未指定文件字符集导致的解码异常

  • 字符串对象互相转换时使用默认编码导致的异常

之后将会分别对两类异常的处理方法做说明。实际上, 第一类错误本质上则是 python 自己运行时打开文件进行解码造成的异常, 就是第二类错误! 我们所犯的解码异常,就是

字符串对象互相转化时没有指定字符编码

黄金原则

本文章之所以比其他写编码的文章稍微多一点价值的原因,在于本文在这里——第一章的最后一小节——就用最大的字体写了处理这类异常的黄金原则

不要惊慌

以及在此之下的,你真正可以掌握的,避免这类异常的黄金原则

只有在IO的时候,才进行转换

这意味着

  1. 因为某些原因, python 打开流读取出的是str,所以用你知道的每一种编码把它解码成unicode

  2. 大概是因为同样的原因,python 的输出也是str, 但是任何一个unicode 只有到要输出的时候才编码成str

  3. 在此之间,放弃该死的str,忘了它,当你开始处理的时候,确保你的每一个字符串对象都是unicode

掌握了以上原则,会避免99%的编码异常发生。当然,正在阅读这篇文章的人中有80%肯定犯过了1000次以上这种错误,去避免剩下1%的发生,而还有20%的人刚开始准备写python,他们会在看完这篇文章后犯完100%的错误,本文的作者正在和80%的人一起微笑着等他们第二遍来看这篇文章。
顺便说一下,这篇文章到这里主要内容就结束了,如果你想找到解决方法和原因,上面已经说的清清楚楚了,接下来主要是各种重复和闲谈,帮助你了解这之后的内幕,不过第二次来看的同学们记得往下看哦

第一类异常

一点小trick

第一类异常是python 自己打开你写的源文件时抛出的解码异常,这句话被说了两遍说明它一定——很不重要,不过你也可以当做一个冷知识储备一下。

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

所有的这类异常都是因为你在源文件写代码时中直接使用了国际化文本——也就是你没有办法在ascii码表里找到的字符。同时你“聪明”的没有做下面说的这一件事

在文件的开头使用注释声明文件编码

# coding:文件编码

pep263

如果你有审慎的阅读出错信息,你一定会注意到一个网址出现在其中。没错,那就是python社区的技术提案 PEP(python enhancement proposals), 涵盖了从版本更新特性至python格式指南的一切东西,如果你有一个昏昏欲睡的下午的话,可以浪费一点时间看看它。

在pep263里,详细的介绍了某种异常发生的原因,以及它提出的一种声明注释的解决方案。接下来我们简要介绍的一些内容你都可以在上面找到,当然它是英文的

原因

自从pep263成为python标准后,python的编译器或者说是编码器在开始解释前,先要经过以下几个步骤:

  1. 读出文件内容

  2. 将内容根据文件编码解码成为unicode

  3. 分词标注

  4. 解释它,并把每一个直接写出的unicode(u'什么鬼')创建一个unicode对象,对str对象,将会从unicode按照文件编码再编码成为str对象

异常原因在于,python的默认文件编码,不是utf-8,不是gbk,而是 ascii

快出来看上帝

他们彼此商量说,来吧,我们要作砖,把砖烧透了。他们就拿砖当石头,又拿石漆当灰泥。

他们说,来吧,我们要建造一座城和一座塔,塔顶通天,为要传扬我们的名,免得我们分散在全地上。
耶和华降临,要看看世人所建造的城和塔。
耶和华说,看哪,他们成为一样的人民,都是一样的言语,如今既作起这事来,以后他们所要作的事就没有不成就的了。
我们下去,在那里变乱他们的口音,使他们的言语彼此不通。
于是,耶和华使他们从那里分散在全地上。他们就停工,不造那城了

本文作者之所以在这里引用一段旧约(某知道里的答案),完全是因为作者想展示一下自己的逼格。事实上,本章关于第一类异常的处理在第一小节就已经结束了,后面完全是杂谈,但其实也许是很重要的

上帝机智的搅乱了人类的语言的1000年后,本文作者觉得可能是上帝的第二次降临,人类中最聪明的一群人,也许也是最蠢的,程序员,开始想要在自己的处理对象里增加字符了。

考虑到转换的问题,很容易就想到,如果把每一个字母,每一个标点,每一个符号与计算机中特殊的一位一一对应的话,就能够实现对字符的处理了。那么,这里假设你已经有一定的计算机底层知识了,这样一个唯一的对应的编码至少需要多少位?

这里提供一些数据, 所有大小写字母一共52个,0~9数字需要10个,加上逗号,句号,感叹号...

答案是 7

ascii码,也就是美国信息交换标准码(American Standard Code for InfORMation Interchange),1967年发布,7位字符编码中影响最大的一种。二进制取值范围0000000~1111111,十六进制表示00h~7fh

事实上当时ascii码主要是用于电传打字机的,但是现在已经基本上一统计算机的天下。但它的问题同样很严重,就在它的名字里,它实在太美国化了。阿拉伯文,日语,当然还有我们的中文,通通找不到自己的位置,于是出现无穷多种扩展ascii编码,它们的前7fh的编码与ascii保持一致,而使用自己的扩展位实现对其他语言及符号的编码

我们统称这一类为ANSI编码标准,在这里各国的程序员们就开始各自发挥了:

  • gb大家族,我朝官方认证出品的一系列字符集

  • latin大家族,主要是对拉丁字母及西欧一些国家的字母编码

  • Big 5,呆湾主要使用的针对繁体中文的编码
    ...

你可以想象这是有多么混乱,实际上都不用想象,现在还有无数人在求助,我的文档打开乱码怎么办

因此,Unicode响应时代的号召,横空出世。Unicode使用16位编码,编码范围0000h~ffffh,它对还在捉对厮杀的各国程序员说,别打了,我们一个字符集包括世界上所有字符就好啦

但是,Unicode只是给定了字符与编码的对应关系,它的实现方式还是有很多种,其中就有UTF大家族(其实是美帝的程序员发现它们要为一辈子都可能见不到的中文,把英文编码提高一个字节时,wtf!)

于是就有了UTF-8,使用一个字节表示英文,而三个字节表示中文的编码方式

注释声明

在一大段闲谈之后,我们简单的说明了各大字符集的由来,所以,现在问题来了,面对各国程序员的各种编码的文件,一门编程语言应该如何处理呢?

对于python,它的默认文件编码是ascii码,在遇到国际化文本,也就是其他编码字符集时,就会无法编码(老天,这个编码都超过ffh了!)

因此,呼应文章开头,pep263指出,python的程序员们都应该在文件的开头写上文件的默认编码,同时一个文件只能有一种编码!也就是:

# coding:文件编码

至于为什么与你平常所见到的模式:

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

不一样,本文作者会轻易告诉你-*-是装饰用的吗

第二类异常

Unicode会梦见小绵羊吗?

在python中,其实是python2中,与其他语言不同的是,有两个经常被用来实际操作的字符串对象

  • str

  • Unicode

要说明两者之间的关系,实在不是一个——很难的问题。我们可以非常非常非常——容易的得到对象的继承关系,如下图:

> object
  >> basestring
     >>> str
     >>> --
     >>> unicode

可以看到,unicode对象与str对象都继承自basestring。basestring是一个抽象类,字符串及其操作由子类str及unicode各自实现。所以

基本上所有str能进行的操作unicode都能进行

编码与解码

在python中,我们所说的编码encode,特指从unicode转换成指定编码的str对象

str = unicode.encode(字符编码)

而所说的解码decode,特指从指定编码的str对象转换为unicode对象

unicode = str.decode(字符编码)

如果你有好好的阅读来看上帝把那一节,就很容易理解这二者的转换,相当于我们把不同字符集中对字符的编码与Unicode全世界统一的编码互相转换。

而python2最大的直钩也在于此,它的默认编码是ascii

然而ascii早已看穿了一切

我们之所以要重复提ascii,是因为它真的很重要!理解它是python2默认编码将会让你真正理解第二类异常的原因:

进行编码解码时没有指定字符集编码,python默认使用ascii进行编码解码

因为ascii仅包含英文大小写及几十个常用符号,因此,当你的编码解码的对象里包含中文或者其他乱七八糟东西的时候

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

Do you know your object?

在这一节,我们将会谈到何时会触发第二类异常,也就是所谓的情景检查。事实上,在本文作者看来,所有的第二类异常都在一种情形下发生:

程序员混用了unicode与str对象

一旦开始错误的使用unicode或者str,都将很有可能导致第二类异常。然而,遗憾的是,直到它抛出了异常,大部分没读过这篇文章的人依然没有意识到问题在哪里。其主要原因在于:

  1. str对象支持的方法与unicode基本完全一样

  2. str与unicode都是继承自basestring,大部分对字符串操作的方法只会检查是不是basestring类及其子类

  3. 任何一个类都来自object(这里指新类),都默认包含内建方法__str__,该方法用于将实例转换成str对象,换言之,你能够print任何一个对象,都因为默认使用内建方法转换了。各个类都可以改写这个内建方法,而unicode改写为使用默认编码解码

这就使得一个初学者的程序中,字符串对象既有unicode,也有str,而他完全没有意识到,当然也是由于大部分市面上的书在这一点上都及其不负责任。想象一下,当你以为自己的对象a是一个str,而实际上是一个unicode,你想当然的进行print输出时,就会默认调用unicode的__str__进行转化输出,在这里进行了默认编码ascii的解码,error!同理适用于当你把一个str当unicode用的时候

一旦你开始混用两种对象,在你不注意的地方,就会发生默认编码解码!

另外一种稍微可以谅解的情况是,python2关于文件流的封装实在太过坑爹,基本上所有文件流最终返回和写入的都是str对象。简单的举个例子,你打开一个文件,按行读取的每一行,都是一个str对象!那些只告诉你这样可以读,不告诉你返回类型(虽然写了你也不大可能注意)的技术博客都是在耍流氓!

    with open('data.txt', 'r') as f:
        for line in f:
            line 是一个str对象!

所以在看到这里的时候,请务必检查你的程序,检查你的每一个字符串对象,确定它是你想要的类型,要知道,我们所接触的大部分数据都会有中文,千万不要等到报错了才开始纠错

Do you know your object?
No!?
Go to know your object!

放过str,请找unicode

为什么我们要放弃str?

简单的理由,str不仅需要我们知道它的编码,还需要根据输出编码做转换。假设你有一个utf8编码的str对象,想要输出到gbk编码的控制台上,你要这么做:

  1. utf8解码成unicode

  2. unicode编码成gbk

为什么我们不从一开始对象处理的时候就用unicode!

粗暴的理由,python3里面已经没有str这种东西了!

请记住黄金原则

只有在IO的时候,才进行转换

这意味着

  1. 因为某些原因, python 打开流读取出的是str,所以用你知道的每一种编码把它解码成unicode

  2. 大概是因为同样的原因,python 的输出也是str, 但是任何一个unicode 只有到要输出的时候才编码成str

  3. 在此之间,放弃该死的str,忘了它,当你开始处理的时候,确保你的每一个字符串对象都是unicode

是不是在哪里看到过? 不要在意这些细节~

按照黄金原则编写能确保你的每一个进行处理的字符串对象都是unicode,同时只在io处进行转换确保你只有在这个时候才需要考虑编码的问题,也符合面向对象封装的概念,也是最pythonic的做法

如果你还不知道什么是pythonic,请直接运行以下python代码

import this

上面所说的是最正确的解决方法,当然有同学就会问啦,下面这种为什么不是最正确的呢?

import sys
sys.setdefaultencoding(字符编码)

这种方法是在饮鸩止渴,完全没有解决你的实际代码问题。它只是将python默认编码替换成了你想要的编码(utf-8之类),一旦有新的编码类型的str对象出现,你的程序就会重新开始报错。所以不推荐这种方法,它会掩盖掉你程序的大部分问题。

异常蛋疼的windows控制台

简单粗暴

就在不久前,本文作者在服务器上部署爬虫代码,就不得不在控制台输出(当然不是因为作者懒得用其他方式跑代码),结果是一连串的乱码,自认不是新手的作者完全不能忍了,于是心平气和的坐下来研究了下windows控制台的编码

事实上,windows的控制台的字符集编码不叫字符集编码,而叫代码页,多么古怪的名字!于是我们很直接的查到了utf-8的代码页是65001

然后再输出的时候发现,每log一行就在报一行的error,看输出信息是log的流往控制台写的时候报的错,不过既然能打印出log,本文作者决定忽略掉那些error

所以

  • 把代码页设置为65001 chcp 65001

  • 如果打印出了log,忽略那些错误把~

本小节是真的没有查资料,如有错误和更好的解决方法,请不吝指正

--结束END--

本文标题: python编码的意义

本文链接: https://www.lsjlt.com/news/192199.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • python编码的意义
    编码,还是编码! python2的直钩——编码异常 当你用python打开一篇中文文档,准备读取里面的数据开始实验...当你处理好你的数据,打算打印出易于阅读的结果给boss检查...甚至当你刚刚开始编写自己的代码,就写了一句话... t...
    99+
    2023-01-31
    意义 python
  • Python编码时应该注意的事情有哪些
    本篇文章给大家分享的是有关Python编码时应该注意的事情有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在编程过程中,多了解语言周边的一些知识,以及一些技巧,可以让你加速...
    99+
    2023-06-17
  • Python中的路径API对于并发编程有何重要意义?
    Python作为一种高级编程语言,其在实现并发编程方面的表现相当出色。在Python中,路径API是非常重要的一部分,它可以为并发编程提供必要的支持。本文将会探讨Python中路径API的重要意义,并且提供相关的示例代码。 路径API是指用...
    99+
    2023-06-29
    并发 path api
  • python中__init__的意义以及作用
    目录python 中 __init__的用法和含义补充:Python类中__init__()的作用python 中 __init__的用法和含义 python 中 __init__ ...
    99+
    2023-02-27
    python __init__用法 python __init__用法
  • python3的url编码和解码,自定义
    因为很多时候要涉及到url的编码和解码工作,所以自己制作了一个类,废话不多说 码上见!# coding:utf-8 import urllib.parse class Urlchuli(): """Url处理类,需要传入两个实...
    99+
    2023-01-31
    自定义 url
  • Python开发注意事项:避免常见的编码错误
    Python作为一种流行的编程语言,在软件开发领域越来越受欢迎。然而,由于Python语言的特性,有时候会出现一些编码错误。本文将介绍一些常见的Python编码错误,以及避免这些错误的方法,希望能帮助开发者更好地编写Python代码。使用合...
    99+
    2023-11-22
    异常处理 编码规范 Python错误处理
  • 解析HTTP状态码的意义和作用
    HTTP(Hypertext Transfer Protocol)是一种用于在网络中传输超文本的应用层协议。在HTTP协议中,服务器和客户端之间通过交换消息来完成数据通信。在客户端向服务器发送请求并得到响应时,服务器会通过HTTP状态码来表...
    99+
    2023-12-26
    HTTP状态码 理解 用途
  • Python面向对象基础:编码细节和注意
    在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名称空间 本篇是第4篇,用一个完整的示例来解释面向对象的一些细节。 例子的模型是父类Employe和子类Manag...
    99+
    2023-01-30
    面向对象 细节 基础
  • ADO.NET批注在编程中的意义是什么
    这篇文章主要讲解了“ADO.NET批注在编程中的意义是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ADO.NET批注在编程中的意义是什么”吧!ADO.NET批注使您能够在不修改基础架构...
    99+
    2023-06-17
  • 浅谈Java编程ToString()方法重写的意义
    上一篇文章我们介绍了java tostring方法重写代码示例,接下来,我们简单聊聊java编程tostring()方法重写的意义。toString()就是是重写,对于一般的对象来说都会有这个方法,其实这个方法的目的,主要就是将对象按字符串...
    99+
    2023-05-31
    java tostring() ava
  • python中 __init__的意义及作用是什么
    这篇文章主要介绍“python中 __init__的意义及作用是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“python中 __init__的意义及作用是什么”文章能帮助大...
    99+
    2023-07-05
  • 编码和Python的bytearray
    unicode    是  编码规范          ===》 http协议GBK UTF-8  是 字符集  编码方法   ===》 Apache  nginxPython 3.Xbytes 和 str 的区别在于bytes是byte的...
    99+
    2023-01-31
    Python bytearray
  • Python编码规范摆脱Python编码噩梦
    目录1. Python 3 中 str 与 bytes2. Python 2 中 str 与 unicode3. 如何检测对象的编码4. 编码与解码的区别5. 如何设置文件编码博客原...
    99+
    2022-11-12
  • linux之系统编码,python编码,
    如果你对python2和python3的中编解码很清楚,这里我认为你很清楚。具体参考文档:“python2 encode和decode函数说明.docx”“字符编码——从ASCII开始.docx”以上所有文档均为本地文档。sys.getde...
    99+
    2023-01-31
    系统 linux python
  • Python HTML编码解码
    >>> import HTMLParser >>> h = HTMLParser.HTMLParser() &g...
    99+
    2023-01-31
    Python HTML
  • Python Unicode编码
    使用技巧事实上,只要遵守以下规则,可以规避90%由于Unicode字符串处理引起的bug,剩下的10%通过python的库和模块能够解决。程序中出现字符串时一定要加个前缀u。不要用str()函数,用unicode()代替。不要用过时的str...
    99+
    2023-01-31
    Python Unicode
  • Python中的面向对象是否没有意义
    Python中的面向对象是否没有意义,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。近来,许多人都在抨击面向对象,虽然我不认为面向对象本身有什么问题,但我觉得至少在 Pyth...
    99+
    2023-06-15
  • python编程是什么意思
    Python编程是指使用Python语言进行软件开发或编写脚本的过程。Python是一种高级编程语言,它具有简单易学、可读性强以及功...
    99+
    2023-09-22
    python
  • 了解HTTP常见状态码及其意义
    了解常见的HTTP状态码及其含义HTTP(HyperText Transfer Protocol)是一种在互联网上进行数据传输的协议。在使用HTTP时,客户端向服务器发送请求,服务器对请求进行处理后返回相应的HTTP状态码。通过HTTP状态...
    99+
    2023-12-26
    HTTP状态码 含义:
  • Python中的编码问题
    视频汇总首页:http://edu.51cto.com/lecturer/index/user_id-4626073.html对于Python的初学者来说,编码问题相当令人头疼。本文就根据我在学习过程中遇到的问题简单谈一下Python中的编...
    99+
    2023-01-31
    Python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作