小编典典

Python默认字符串编码

python

Python在何时,何地以及如何将隐式编码应用于字符串,或者隐式转码(转换)?

那些“默认”(即隐含)编码是什么?

例如,编码是什么:

  • 字符串文字?

    s = "Byte string with national characters"
    

    us = u”Unicode string with national characters”

  • 类型转换为Unicode或从Unicode转换为字节字符串?

    data = unicode(random_byte_string)
    
  • 当从文件或终端写入字节和Unicode字符串时?

    print(open("The full text of War and Peace.txt").read())
    

阅读 414

收藏
2020-12-20

共1个答案

小编典典

这里涉及Python功能的多个部分: 读取源代码并解析字符串文字转码打印 。每个都有自己的约定。

简短答案:

  • 出于代码解析的目的:
    • str(Py2)-不适用,从文件中获取原始字节
    • unicode(Py2)/ str(Py3)-“源编码”,默认为ascii(Py2)和utf-8(Py3)
    • bytes(Py3)-无,非ASCII字符在文字中被禁止
  • 为了进行转码:
    • both(Py2)- sys.getdefaultencoding()ascii几乎总是)
    • 存在隐式转换,通常会导致UnicodeDecodeError/UnicodeEncodeError
    • both(Py3)-无,在转换时必须明确指定编码
  • 出于I / O的目的:
    • unicode(Py2)-<file>.encoding如果设置,否则sys.getdefaultencoding()
    • str(Py2)-不适用,写入原始字节
    • str(Py3)- <file>.encoding,始终设置,默认为locale.getpreferredencoding()
    • bytes(Py3)-没有,而是print产生它repr()

首先,对一些术语进行澄清,以便您正确理解其余内容。 解码 是从 字节字符(Unicode或其他)的转换 ,而 编码
(作为一个过程)则相反。请参阅绝对最低知识,每个软件开发人员绝对,肯定必须了解Unicode和字符集(无借口!)– Joel on
Software
以获得与众不同。

现在…

读取源代码并解析字符串文字

在源文件的开头,您可以指定文件的“源编码”(其确切效果将在后面说明)。如果未指定,则默认值为asciiPython
2和utf-8Python3。UTF-8BOM与utf-8编码声明具有相同的作用。

Python 2

Python
2将源作为原始字节读取。看到Unicode文字时,它仅使用“源编码”来解析Unicode文字。(这比实际情况要复杂得多,但这是实际效果。)

> type t.py
#encoding: cp1251
s = "абвгд"
us = u"абвгд"
print repr(s), repr(us)
> py -2 t.py
'\xe0\xe1\xe2\xe3\xe4' u'\u0430\u0431\u0432\u0433\u0434'

<change encoding declaration in the file to cp866, do not change the contents>
> py -2 t.py
'\xe0\xe1\xe2\xe3\xe4' u'\u0440\u0441\u0442\u0443\u0444'

<transcode the file to utf-8, update declaration or replace with BOM>
> py -2 t.py
'\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4' u'\u0430\u0431\u0432\u0433\u0434'

因此, 常规字符串将包含文件中的确切字节。Unicode字符串将包含“源编码”解码文件的字节的结果。

如果解码失败,您将得到一个SyntaxError。如果在未指定编码的情况下文件中包含非ASCII字符,则相同。最后,如果使用unicode_literalsfuture,那么解析时任何常规字符串文字(仅在该文件中)都将被视为Unicode文字,这意味着所有意义。

Python 3

Python
3使用“源编码”将整个源文件解码为一系列Unicode字符。此后将进行任何解析。(特别是,这使得在标识符中包含Unicode成为可能。)由于所有字符串文字现在都是Unicode,因此不需要其他转码。在字节字面量中,禁止使用非ASCII字符(此类字节必须使用转义序列指定),从而完全避免了该问题。

转码

根据开始时的说明:

  • str(Py2)/ bytes(Py3)- 字节 =>只能是decoded (直接,即;详细信息如下)
  • unicode(Py2)/ str(Py3)- 字符 =>只能是encoded

Python 2

在这两种情况下,如果未指定编码,sys.getdefaultencoding()则使用。它ascii
(除非你取消注释代码块site.py或做一些其他的黑客是一个灾难)。因此,
出于代码转换的目的,sys.getdefaultencoding()是“字符串的默认编码”。

现在,有一个警告:

  • 当转换时, adecode()encode()-使用默认编码-隐式完成str<->unicode

    • 以字符串格式(SO的UnicodeDecodeError/UnicodeEncodeError问题的三分之一与此有关)
    • 尝试encode()astrdecode()a时unicode(SO问题的第二三分之一)

Python 3

根本没有“默认编码”:str和之间的隐式转换bytes现在被禁止。

  • bytes只能decoded和str- encoded,和encoding参数是强制性的。
  • 转换bytes->str(包括隐式)产生了它repr()(仅对调试打印有用),从而完全避免了编码问题
  • str->bytes禁止转换

列印

这件事与变量的值无关,但与它被printed时在屏幕上看到的内容有关,以及与ingUnicodeEncodeError时是否会得到一个变量有关print

Python 2

  • 如果设置了A,unicode则为encoded <file>.encoding;否则,将其隐式转换str为以上所述。(UnicodeEncodeErrorSO问题的最后三分之一属于此处。)
    • 对于标准流,在启动时会从各种特定于环境的来源中猜测流的编码,并且可以用PYTHONIOENCODINGenvvar覆盖它。
  • str的字节原样发送到OS流。您将在屏幕上看到的具体字形取决于终端的编码设置(如果类似UTF-8,则如果打印无效的UTF-8字节序列,您可能什么也看不到)。

Python 3

更改为:

  • 现在file以文本vs二进制打开,以mode本机接受strbytes,相应地,并且完全拒绝处理错误的类型。文本模式文件始终有一个encoding设置,locale.getpreferredencoding(False)即默认设置
  • print对于文本流,仍然将所有内容隐式转换为str,在按照上述方式bytes打印时repr(),完全避免了编码问题
2020-12-20