sublime3上的Python3编码问题

问题描述

用Python打开Alice in the wonderland文本,sublime报错,命令行运行正常(卡了1整天)

报错的异常是

1
UnicodeDecodeError:'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)
  • UnicodeDecodeError: Unicode的解码出现错误:

  • ‘ascii’ codec can’t decode

    • 要将字符串解码为Unicode,是以ascii的形式去解码(该字符串变为Unicode)的

    • 但此处通过ascii的方式,却无法解码(can’t decode)

      此处的codec,意思是:编解码(器),是Python内部的模块,用来编码或解码(字符串)的

  • bytes 0xef in position 0: 错误位置
  • ordinal not in range(128)序数不在范围内

将一个字符串,通过ascii的方式,去解码,想要获得Unicode字符串,结果出错了

如果出现这个错误,通常表示你读取文本时指定的编码不正确。

Unicode编码

字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码

关于Unicode

Unicode是一种字符集,它为每一种现代或古代使用的文字系统中出现的每一个字符都提供了统一的序列号,规定了符号的二进制代码,但没有规定这个二进制代码应该如何存储。也就是说:Unicode的编码方式是固定的,但是实现方式根据不同的需要有跟多种,常见的有UTF-8、UTF-16和UTF-32等。更多的介绍大家可以参看维基百科:Unicode

在Python 3.0之后的版本中,所有的字符串都是使用Unicode编码的字符串序列,同时还有以下几个改进:

  • 1、默认编码格式改为unicode
  • 2、所有的Python内置模块都支持unicode
  • 3、不再支持u’中文’的语法格式

utf-8 是对 unicode 存储的实现方式

unicode只定义字符对应的数字,但没有规定这些数字如何存储起来,比如像中文的『我』字存储时需要两个字节来表示,而英文字母A却只需要一个字节,有些其他的字符可能需要3-4个字节。

  • 如果统一规定每个字符用3个或者4个字节来存储,那么每个英文字符都必然需要额外2到3个0,这对存储是很大的浪费。
  • 如果每个字符按照实际需要的字节数来存储,计算机就分不清三个字节是表示三个字符还是一个字符。

utf-8 是对 unicode 编码存储的一种实现方式,同样的还有utf-16, utf-32。

utf-8 是使用最广泛的编码方式,采用变长的编码方式,可以使用1-4个字节来表示一个字符; utf-16 用2个或4个字节,utf-32用4个字节表示。编码规则如下:

  1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母, UTF-8编码和ASCII码是相同的。
  2. 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

解决方案

搜索关键字 “sublime默认编码 python”

在打开和写入文件时,写明编码格式即可

1
2
3
4
encoding='utf8'

data=open("cardno.txt",encoding='utf8')
result=open("result.txt","w",encoding= 'utf8') #指定文件的编码格式

也可以打开源文件修改编码格式

也可参考python cookbook 5.1节

结果问题又出现了,以上方案并没有解决了问题

关键是在命令行运行不会报错,在sublime上就会,说明问题出在sublime,而不是在代码上

在sublime上输入如下代码

我擦,python3默认编码是utf-8啊

同样的代码在命令行里

1
2
3
4
5
6
>>> print (sys.stdin.encoding)
UTF-8
>>> print (sys.stdout.encoding)
UTF-8
>>> print (sys.stderr.encoding)
UTF-8

啊哈,问题找到了,但到底是sublime哪里出问题了?

想到的是刚开始用sublime根据书(《Python编程:从入门到实践》)里设置的python3-build-system

(好吧。我才承认这个是在V站上搜到的)

自己建的python3_build_system,只有一句话

1
"cmd" : ["/usr/local/bin/python3","-u", "$file"],

没有设置具体的编码格式

导致 Python 无法判断出正确的 stdin/stdout/stderr 编码

解决方法就是

到系统自带的python_build_system里复制一份(找到这个文件的最好方法是安装插件 PackageResourceViewer), 粘贴到自己新建的build_system,并将第一行的python改成自己python3的路径(查看命令行里输入type -apython3),就ok了(这里有个蛋疼的地方,改了不是立即生效的,我不知道什么原因,改了好几次都没有生效,后来就突然好了,再去验证了下,改为原来的在改,竟然立即生效了,算了,算了不去纠结了)

sublime的设置文件夹 OS X: ~/Library/ApplicationSupport/Sublime Text 3

如果你的python安装目录没有在系统环境变量Path中,那么build会失败。系统都找不到python这个命令,执行个毛啊,这个时候你有三个选择:

  1. 把python安装路径加到系统环境变量Path中,这个就不说了,应该都会吧….

  2. 修改默认的Python.sublime-build,墙裂建议不要这么做!

  3. 自己动手写一个xxx.sublime-build!

参考资料

https://www.v2ex.com/t/163786

https://www.cnblogs.com/dengyg200891/p/6059277.html

搜索关键词 UnicodeEncodeError site:v2ex.com