Python을 개발하는 모든 사람들이 문자 인코딩 문제로 인해 혼란스러워 한다고 합니다. 가장 일반적인 오류는 UnicodeEncodeError 및 UnicodeDecodeError입니다. 불행히도 오류는 다른 곳에서 나타나고 문제는 항상 반복됩니다. . str을 유니코드로 변환하기 위해 decode 또는 encode 방법을 사용해야 하는지 기억하기 어렵습니다. 무엇이 문제일까요?
이 문제를 명확히하기 위해 파이썬 문자열의 구성과 문자 인코딩의 세부 사항까지 심층 분석을 수행하기로 결정했습니다.
컴퓨터에 저장된 모든 데이터, 텍스트 문자, 사진, 비디오, 오디오, 소프트웨어는 모두 01의 바이트 시퀀스로 구성되며 1바이트는 8비트와 같습니다.
문자는 기호입니다. 예를 들어 한자, 영문자, 숫자, 구두점 모두 문자라고 할 수 있습니다.
바이트는 저장 및 네트워크 전송에 편리한 반면, 문자는 표시 및 읽기 쉬운 데 사용됩니다. 예를 들어, 하드 디스크에 저장된 문자 "p"는 바이너리 데이터의 문자열01110000
으로, 길이가 1바이트를 차지하며
텍스트를 편집기로 열면 각 문자를 볼 수 있으며, 최종적으로 디스크에 저장되며 바이너리 바이트 시퀀스 형태로 저장됩니다. 그런 다음 문자에서 바이트로 변환하는 과정을 인코딩이라고 하고, 그 반대 과정을 디코딩이라고 합니다. 이 두 가지를 가역적 과정이라고 합니다. 인코딩은 저장과 전송을 위한 것이고, 디코딩은 표시와 읽기를 위한 것입니다.
예를 들어 문자 "p"는 1바이트 길이를 차지하는 일련의 이진 바이트 01110000으로 인코딩되어 하드 디스크에 저장됩니다. "Zen" 문자는 3바이트 길이를 차지하는 "11100111 10100110 10000101"로 저장될 수 있습니다. 왜 가능합니까? 이에 대해서는 나중에 이야기하겠습니다.
파이썬 코딩은 왜 그렇게 고통스럽나요? 물론 이를 개발자 탓으로 돌릴 수는 없다.
Python2는 기본 인코딩으로 ASCII 문자 인코딩을 사용하고 ASCII는 중국어를 처리할 수 없기 때문에 UTf-8을 사용하지 않는 이유는 무엇입니까? 왜냐하면 Dad Guido가 1989년 겨울에 Python용 첫 번째 코드 줄을 작성했고, 첫 번째 버전이 공식적으로 오픈 소스로 공개되어 1991년 2월에 출시되었으며, Unicode가 1991년 10월에 출시되었기 때문에 UTF-언어라는 Python이 만들어졌음을 의미합니다. 8명은 아직 태어나지 않았기 때문에 이 사람도 그 중 한 명이었습니다.
Python도 문자열 유형을 유니코드와 str의 두 가지 유형으로 나누어 개발자를 혼란스럽게 합니다. Python3은 문자열을 완전히 재구성하여 한 가지 유형만 유지합니다.
Python2는 문자열을 unicode와 str의 두 가지 유형으로 나눕니다. 본질적으로 str은 이진 바이트의 시퀀스입니다. 아래 예제 코드에서 볼 수 있듯이 str 유형의 "Zen"은 16진수 xecxf8로 인쇄되며 해당 이진 바이트 시퀀스는 '11101100 11111000'입니다.
>>> s = '禅' >>> s '\xec\xf8' >>> type(s) <type 'str'>
그리고 유니코드 유형 u"Zen"에 해당하는 유니코드 기호는 u'u7985′
>>> u = u"禅" >>> u u'\u7985' >>> type(u) <type 'unicode'>
유니코드 기호를 파일로 저장하거나 네트워크로 전송하려면 str로 변환해야 합니다. 인코딩 처리를 통해 유형을 입력하므로 Python은 유니코드에서 str로 또는 그 반대로 변환하는 encode 메소드를 제공합니다.
encode
>>> u = u"禅" >>> u u'\u7985' >>> u.encode("utf-8") '\xe7\xa6\x85'
decode
>>> s = "禅" >>> s.decode("utf-8") u'\u7985' >>>
str과 유니코드 사이를 변환하기 위해 인코딩을 사용할지 디코드를 사용할지 기억하지 못하는 초보자가 많습니다. str은 실제로 이진 데이터의 문자열이고 유니코드는 문자입니다. (symbol), 인코딩은 문자(기호)를 바이너리 데이터로 변환하는 과정이므로 유니코드에서 str로 변환하려면 encode 방법이 필요하고, 반대로 decode 방법이 필요합니다.
encoding always takes a Unicode string and returns a bytes sequence, and decoding always takes a bytes sequence and returns a Unicode string”.
str과 유니코드 간의 변환 관계를 명확히 한 후 UnicodeEncodeError 및 UnicodeDecodeError 오류가 발생하는 경우를 살펴보겠습니다.
UnicodeEncodeError는 유니코드 문자열이 str 바이트 시퀀스로 변환될 때 발생합니다. 유니코드 문자열의 문자열을 파일에 저장하는 예를 살펴보겠습니다.
# -*- coding:utf-8 -*- def main(): name = u'Python之禅' f = open("output.txt", "w") f.write(name)
Error log
UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 6-7: ordinal not in range(128)
UnicodeEncodeError는 왜 발생합니까?
write 메소드를 호출할 때 Python은 먼저 문자열이 어떤 유형인지 결정합니다. str인 경우 str 유형 문자열 자체가 바이너리 바이트 시퀀스이기 때문에 인코딩 없이 파일에 직접 기록됩니다.
문자열이 유니코드 유형인 경우 먼저 인코딩 메소드를 호출하여 유니코드 문자열을 파일에 저장하기 전에 바이너리 str 유형으로 변환합니다. 인코딩 메소드는 파이썬의 기본 ASCII 코드를 사용하여 인코딩합니다
다음과 같습니다.
>>> u"Python之禅".encode("ascii")
그러나 ASCII 문자 집합에는 한자를 제외한 라틴 문자 128자만 포함되어 있으므로 'ascii' 코덱에서는 문자를 인코딩할 수 없다는 오류가 발생하는 것으로 알고 있습니다. 인코딩을 올바르게 사용하려면 UTF-8, GBK 등 중국어 문자가 포함된 문자 세트를 지정해야 합니다.
>>> u"Python之禅".encode("utf-8") 'Python\xe4\xb9\x8b\xe7\xa6\x85' >>> u"Python之禅".encode("gbk") 'Python\xd6\xae\xec\xf8'
그래서 유니코드 문자열을 파일에 올바르게 쓰기 위해서는 미리 문자열을 UTF-8 또는 GBK 인코딩으로 변환해야 합니다.
def main(): name = u'Python之禅' name = name.encode('utf-8') with open("output.txt", "w") as f: f.write(name)
当然,把 unicode 字符串正确地写入文件不止一种方式,但原理是一样的,这里不再介绍,把字符串写入数据库,传输到网络都是同样的原理
UnicodeDecodeError 发生在 str 类型的字节序列解码成 unicode 类型的字符串时
>>> a = u"禅" >>> a u'\u7985' >>> b = a.encode("utf-8") >>> b '\xe7\xa6\x85' >>> b.decode("gbk") Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'gbk' codec can'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: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128) >>>
str 与 unicode 字符串 执行 + 操作是,Python 会把 str 类型的字节序列隐式地转换成(解码)成 和 x 一样的 unicode 类型,但Python是使用默认的 ascii 编码来转换的,而 ASCII 中不包含中文,所以报错了。
>>> y.decode('ascii') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can'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'Python\u4e4b\u7985'
以上内容都是基于 Python2 来讲的,关于 Python3 的字符和编码将会另开一篇文章来写,保持关注。
위 내용은 Python 코딩에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!