Heim  >  Artikel  >  Backend-Entwicklung  >  Eingehende Analyse der Python-Codierung

Eingehende Analyse der Python-Codierung

黄舟
黄舟Original
2017-07-18 13:27:421010Durchsuche

Es wird gesagt, dass jeder, der Python entwickelt, durch das Problem der Zeichencodierung verwirrt ist. Die häufigsten Fehler sind UnicodeEncodeError und UnicodeDecodeError. Leider treten die Fehler an anderen Stellen auf Es ist immer wieder derselbe Fehler und es ist sehr schwierig, sich daran zu erinnern, ob ich str in Unicode umwandeln soll. Was ist das Problem?

Um dieses Problem zu klären, habe ich beschlossen, eine eingehende Analyse der Zusammensetzung von Python-Strings und der Details der Zeichenkodierung durchzuführen

Bytes und Zeichen

Alles Im Computer gespeicherte Daten, Textzeichen, Bilder, Videos, Audios und Software bestehen alle aus einer Folge von 01 Bytes. Ein Byte entspricht 8 Bits.

Ein Zeichen ist ein Symbol. Beispielsweise können ein chinesisches Zeichen, ein englischer Buchstabe, eine Zahl und ein Satzzeichen alle als Zeichen bezeichnet werden.

Bytes eignen sich zur Speicherung und Netzwerkübertragung, während Zeichen zur Anzeige verwendet werden und leicht zu lesen sind. Beispielsweise ist das auf der Festplatte gespeicherte Zeichen „p“ eine Folge binärer Daten 01110000, die ein Byte lang ist

Kodierung und Dekodierung

Der Text, den wir mit dem Editor öffnen Wenn wir ein Zeichen sehen, werden sie alle in Form einer binären Bytefolge gespeichert, wenn sie schließlich auf der Festplatte gespeichert werden. Dann wird der Konvertierungsprozess von Zeichen in Bytes als Kodierung bezeichnet, und der umgekehrte Vorgang wird als Dekodierung bezeichnet. Die beiden Prozesse sind umkehrbar. Die Kodierung dient der Speicherung und Übertragung, die Dekodierung dient der Anzeige und dem Lesen.

Zum Beispiel wird das Zeichen „p“ codiert und als Folge von Binärbytes 01110000 auf der Festplatte gespeichert, wobei die Länge ein Byte beträgt. Das Zeichen „Zen“ kann als „11100111 10100110 10000101“ gespeichert werden und eine Länge von 3 Bytes belegen. Warum ist das möglich? Wir werden später darüber sprechen.

Warum ist Python-Codierung so schmerzhaft? Dies kann natürlich nicht den Entwicklern angelastet werden.

Das liegt daran, dass Python2 die ASCII-Zeichenkodierung als Standardkodierung verwendet und ASCII kein Chinesisch verarbeiten kann. Warum also nicht UTf-8 verwenden? Da Papa Guido im Winter 1989 die erste Codezeile für Python schrieb und die erste Version im Februar 1991 offiziell als Open Source veröffentlicht wurde und Unicode im Oktober 1991 veröffentlicht wurde, bedeutet dies, dass die Sprache Python erstellt wurde. 8 war noch nicht geboren, also war dies einer von ihnen.

Python unterteilt String-Typen auch in zwei Typen, Unicode und Str, was Entwickler verwirrt. Dies ist der zweite Grund. Python3 hat die Zeichenfolgen komplett umgestaltet und nur einen Typ beibehalten. Dies ist eine Geschichte für später.

str und unicode

Python2 unterteilt Zeichenfolgen in zwei Typen: Unicode und str. Im Wesentlichen ist str eine Folge binärer Bytes. Wie aus dem Beispielcode unten ersichtlich ist, wird „Zen“ vom Typ str als hexadezimales xecxf8 gedruckt, und die entsprechende binäre Bytefolge lautet „11101100 11111000“.

>>> s = '禅'
>>> s
'\xec\xf8'
>>> type(s)
<type &#39;str&#39;>

Das entsprechende Unicode-Symbol des Unicode-Typs u"Zen" ist u'u7985′

>>> u = u"禅"
>>> u
u&#39;\u7985&#39;
>>> type(u)
<type &#39;unicode&#39;>

Wenn wir das Unicode-Symbol in einer Datei speichern oder übertragen möchten Im Netzwerk müssen wir den Codierungsprozess durchlaufen, der in den Typ str konvertiert wird. Daher stellt Python die Codierungsmethode für die Konvertierung von Unicode in str und umgekehrt bereit.

kodieren

>>> u = u"禅"
>>> u
u&#39;\u7985&#39;
>>> u.encode("utf-8")
&#39;\xe7\xa6\x85&#39;

dekodieren

>>> s = "禅"
>>> s.decode("utf-8")
u&#39;\u7985&#39;
>>>

Viele Anfänger können sich nicht an den Unterschied zwischen str und unicode erinnern. Verwenden Sie kodieren oder dekodieren Zur Konvertierung. Wenn Sie sich daran erinnern, dass str tatsächlich eine Zeichenfolge binärer Daten und Unicode ein Zeichen (Symbol) ist, ist die Codierung (encode) der Prozess der Konvertierung von Zeichen (Symbolen) in Binärdaten, also ist die Konvertierung von Unicode in str erforderlich Kodierungsmethode und umgekehrt die Dekodiermethode.

encoding always takes a Unicode string and returns a bytes sequence, and decoding always takes a bytes sequence and returns a Unicode string”.

Nachdem wir die Konvertierungsbeziehung zwischen str und Unicode geklärt haben, werfen wir einen Blick darauf, wann UnicodeEncodeError- und UnicodeDecodeError-Fehler auftreten.

UnicodeEncodeError

UnicodeEncodeError tritt auf, wenn eine Unicode-Zeichenfolge in eine Str-Byte-Sequenz konvertiert wird. Schauen wir uns ein Beispiel für das Speichern einer Zeichenfolge aus Unicode-Zeichenfolgen in einer Datei an

# -*- coding:utf-8 -*-
def main():
    name = u&#39;Python之禅&#39;
    f = open("output.txt", "w")
    f.write(name)

Fehlerprotokoll

UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 6-7: ordinal not in range(128)

Warum tritt UnicodeEncodeError auf?

Denn beim Aufrufen der Schreibmethode ermittelt Python zunächst, um welchen Typ es sich bei der Zeichenfolge handelt. Wenn es sich um eine Zeichenfolge handelt, wird sie ohne Codierung direkt in die Datei geschrieben, da die Zeichenfolge selbst eine ist Zeichenfolge einer binären Bytefolge.

Wenn es sich bei der Zeichenfolge um einen Unicode-Typ handelt, wird zuerst die Encode-Methode aufgerufen, um die Unicode-Zeichenfolge in den Binär-Str-Typ zu konvertieren, bevor sie in der Datei gespeichert wird. Die Encode-Methode verwendet zum Codieren den Standard-ASCII-Code von Python

ist äquivalent zu:

>>> u"Python之禅".encode("ascii")

Wir wissen jedoch, dass der ASCII-Zeichensatz nur 128 lateinische Buchstaben enthält, ausgenommen chinesische Zeichen, sodass der „ASCII“-Codec keine Zeichen kodieren kann, scheint ein Fehler zu sein . Um die Kodierung korrekt zu verwenden, müssen Sie einen Zeichensatz angeben, der chinesische Zeichen enthält, z. B. UTF-8, GBK.

>>> u"Python之禅".encode("utf-8")
&#39;Python\xe4\xb9\x8b\xe7\xa6\x85&#39;

>>> u"Python之禅".encode("gbk")
&#39;Python\xd6\xae\xec\xf8&#39;

Um Unicode-Strings korrekt in Dateien zu schreiben, sollten Sie die Strings vorab in die UTF-8- oder GBK-Kodierung konvertieren.

def main():
    name = u&#39;Python之禅&#39;
    name = name.encode(&#39;utf-8&#39;)
    with open("output.txt", "w") as f:
        f.write(name)

当然,把 unicode 字符串正确地写入文件不止一种方式,但原理是一样的,这里不再介绍,把字符串写入数据库,传输到网络都是同样的原理

UnicodeDecodeError

UnicodeDecodeError 发生在 str 类型的字节序列解码成 unicode 类型的字符串时

>>> a = u"禅"
>>> a
u&#39;\u7985&#39;
>>> b = a.encode("utf-8")
>>> b
&#39;\xe7\xa6\x85&#39;
>>> b.decode("gbk")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: &#39;gbk&#39; codec can&#39;t decode byte 0x85 in position 2: incomplete multibyte sequence

把一个经过 UTF-8 编码后生成的字节序列 ‘\xe7\xa6\x85′ 再用 GBK 解码转换成 unicode 字符串时,出现 UnicodeDecodeError,因为 (对于中文字符)GBK 编码只占用两个字节,而 UTF-8 占用3个字节,用 GBK 转换时,还多出一个字节,因此它没法解析。避免 UnicodeDecodeError 的关键是保持 编码和解码时用的编码类型一致。

这也回答了文章开头说的字符 “禅”,保存到文件中有可能占3个字节,有可能占2个字节,具体处决于 encode 的时候指定的编码格式是什么。

再举一个 UnicodeDecodeError 的例子

>>> x = u"Python"
>>> y = "之禅"
>>> x + y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: &#39;ascii&#39; codec can&#39;t decode byte 0xe4 in position 0: ordinal not in range(128)
>>>

str 与 unicode 字符串 执行 + 操作是,Python 会把 str 类型的字节序列隐式地转换成(解码)成 和 x 一样的 unicode 类型,但Python是使用默认的 ascii 编码来转换的,而 ASCII 中不包含中文,所以报错了。

>>> y.decode(&#39;ascii&#39;)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: &#39;ascii&#39; codec can&#39;t decode byte 0xe4 in position 0: ordinal not in range(128)

正确地方式应该是显示地把 y 用 UTF-8 或者 GBK 进行解码。

>>> x = u"Python"
>>> y = "之禅"
>>> y = y.decode("utf-8")
>>> x + y
u&#39;Python\u4e4b\u7985&#39;

以上内容都是基于 Python2 来讲的,关于 Python3 的字符和编码将会另开一篇文章来写,保持关注。

Das obige ist der detaillierte Inhalt vonEingehende Analyse der Python-Codierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn