Python默认字符串编码

iva*_*eev 4 python character-encoding python-2.x python-3.x python-unicode

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

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

例如,什么是编码:

iva*_*eev 8

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

简短的回答:

  • 出于代码解析的目的:
    • str (Py2) -- 不适用,从文件中获取原始字节
    • unicode(Py2)/ str(Py3) -- "源编码",默认为ascii(Py2) 和utf-8(Py3)
    • bytes (Py3) -- none,文字中禁止使用非 ASCII 字符
  • 为了转码:
    • 两者(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) -没有,printING产生其repr()代替

首先,一些术语的澄清,以便您正确理解其余部分。解码是从字节字符(Unicode 或其他)的转换,而编码(作为一个过程)则相反。请参阅每个软件开发人员绝对、肯定地必须了解 Unicode 和字符集的绝对最小值(没有任何借口!)– Joel on Software以获得区别。

现在...

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

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

蟒蛇 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'
Run Code Online (Sandbox Code Playgroud)

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

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

蟒蛇 3

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

转码

根据一开始的澄清:

  • str(Py2)/ bytes(Py3) -- bytes => 只能是decoded (直接,也就是;详情如下)
  • unicode(Py2)/ str(Py3) --字符=> 只能是encoded

蟒蛇 2

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

现在,这里有一个警告:

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

    • 在字符串格式中(关于 Stack Overflow的UnicodeDecodeError/UnicodeEncodeError问题的三分之一是关于这个的)
    • 尝试encode()astrdecode()a 时unicode(堆栈溢出问题的第二个三分之一)

蟒蛇 3

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

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

印刷

这个问题与变量的值无关,但与你在print编辑时在屏幕上看到的内容有关——以及你是否会得到一个UnicodeEncodeErrorwhen printing。

蟒蛇 2

  • A unicodeis encoded with <file>.encodingif set; 否则,它被隐式转换str为如上所述。(UnicodeEncodeErrorSO 问题的最后三分之一属于这里。)
    • 对于标准流,在启动时从各种特定于环境的源猜测流的编码,并且可以用PYTHONIOENCODING环境变量覆盖。
  • str的字节按原样发送到操作系统流。您将在屏幕上看到的具体字形取决于终端的编码设置(如果它是 UTF-8 之类的东西,如果您打印一个无效的 UTF-8 字节序列,您可能什么也看不到)。

蟒蛇 3

变化是:

  • 现在files 打开文本与二进制mode本机接受stror bytes,相应地,并彻底拒绝处理错误的类型。文本模式文件总是有一个encoding集合,locale.getpreferredencoding(False)是默认的.
  • print对于文本流仍然隐式地将所有内容转换为str,在按照上述bytes打印的情况下,repr()完全避免了编码问题