Python 중국어 왜곡 문제에 대한 심층 분석

高洛峰
풀어 주다: 2017-01-13 16:07:13
원래의
1117명이 탐색했습니다.

이 기사에서는 모든 문제를 설명하기 위해 'Ha'를 예로 사용했습니다. 'Ha'의 다양한 인코딩은 다음과 같습니다.
1. UNICODE(UTF8-16),
2; . UTF-8, E59388
3. GBK,B9FE.
1. Python의 str 및 유니코드
Python의 중국어 인코딩은 항상 매우 큰 문제였으며, Python에서 str과 유니코드는 정확히 무엇입니까?
파이썬에서 유니코드라고 하면 일반적으로 유니코드 객체를 가리킵니다. 예를 들어 'haha'의 유니코드 객체는
u'u54c8u54c8'
그리고 str은 이를 나타내는 바이트 배열입니다. 유니코드 객체(utf-8, gbk, cp936, GB2312)를 인코딩한 후의 저장 형식입니다. 여기서는 다른 의미가 없는 단순한 바이트 스트림입니다. 이 바이트 스트림으로 표시되는 콘텐츠를 의미있게 만들려면 올바른 인코딩 형식을 사용하고 디코딩하고 표시해야 합니다.
예:

python 中文乱码问题深入分析

유니코드 객체는 utf-8로 인코딩된 str-s_utf8로 인코딩됩니다. s_utf8은 'xe5x93x88xe5x93x88'을 저장하는 바이트 배열입니다. 그냥 바이트 배열이군요. ㅎㅎ print문을 통해 출력하고 싶으시다면 실망하실텐데요. 왜일까요?

print 문의 구현은 출력 내용을 운영 체제로 전송하기 때문에 운영 체제는 시스템의 인코딩에 따라 입력 바이트 스트림을 인코딩합니다. 이는 UTF-8 형식의 문자열이 "Haha"인 이유를 설명합니다. , 'xe5x93x88xe5x93x88'이 GB2312에 의해 해석되어 "鍝鍚搱"로 표시되므로 출력은 "鍝獚搐"입니다. str은 특정 인코딩 저장 형식인 바이트 배열을 기록한다는 점을 다시 강조하겠습니다. 파일로 출력하거나 인쇄하는 형식은 전적으로 디코딩 인코딩에 따라 어떻게 디코딩되는지에 따라 달라집니다.

str 및 unicode 객체의 변환은 encode 및 decode를 통해 이루어집니다. 구체적인 사용법은 다음과 같습니다.

Convert GBK '하하'를 유니코드로 변환한 다음 UTF8로

python 中文乱码问题深入分析3. 기본 인코딩 설정

위의 데모 코드에 표시된 대로:

python 中文乱码问题深入分析

s(gbk 문자열)가 utf-8로 직접 인코딩되면 예외가 발생하지만 다음 코드를 호출하면 됩니다.


import sys

reload( sys)

sys.setdefaultencoding('gbk')

그러면 변환이 성공할 수 있습니다. 이유는 무엇입니까? Python에서 str 및 unicode의 인코딩 및 디코딩 과정에서 str을 다른 인코딩으로 직접 인코딩하면 str이 먼저 unicode로 디코딩되며 사용되는 인코딩은 일반적으로 기본 인코딩이 ancii이므로 에서는 위의 예에서는 코드의 첫 번째 변환 중에 오류가 발생합니다. 현재 기본 인코딩을 'gbk'로 설정한 후에는 오류가 발생하지 않습니다.

reload(sys)의 경우 Python2.5에서는 초기화 후 sys.setdefaultencoding 메서드를 삭제하므로 다시 로드해야 합니다.

4. 다양한 인코딩 형식으로 파일 조작

파일 형식은 ANSI이고 내용은

abc Chinese


파이썬을 사용하여 읽기

#coding=gbk

print open("Test.txt").read()

결과: abc 중국어

파일 형식을 UTF-8로 변경:

결과: abc涓枃

분명히 여기서 디코딩이 필요합니다:

#coding=gbk

코덱 가져오기

print open("Test.txt").read().decode("utf-8")

결과: abc 중국어

위 test.txt를 에디트플러스로 편집했는데, 윈도우 내장 메모장으로 편집하고 UTF-8 형식으로 저장했더니

실행시 오류가 보고되었습니다:

Traceback( 가장 최근 호출 마지막):

파일 "ChinaTest.py", 3행,

print open("Test.txt").read().decode("utf-8" )

UnicodeEncodeError: 'gbk' 코덱은 위치 0의 문자 u'ufeff'를 인코딩할 수 없습니다: 잘못된 멀티바이트 시퀀스

메모장과 같은 일부 소프트웨어가 UTF-로 인코딩된 파일을 저장하는 것으로 나타났습니다. 도 8에서는 보이지 않는 문자 3개(0xEF 0xBB 0xBF, BOM)가 파일 시작 부분에 삽입됩니다.

따라서 읽을 때 이러한 문자를 직접 제거해야 합니다. Python의 코덱 모듈은 다음 상수를 정의합니다.

#coding=gbk

가져오기 코덱

data = open("Test.txt").read()

if data[:3] == codecs.BOM_UTF8:

data = data[3:]

print data.decode("utf-8")

결과: abc 중국어

5. 파일의 인코딩 형식과 인코딩 문의 역할

소스 파일 인코딩 형식은 문자열 선언에 어떤 영향을 미치나요? 이 문제는 오랫동안 나를 괴롭혔고 이제 마침내 몇 가지 단서를 얻었습니다. 파일의 인코딩 형식에 따라 소스 파일에 선언된 문자열의 인코딩 형식이 결정됩니다. 예:

str = ' ㅎㅎ'

print repr(str)

a. 파일 형식이 utf-8이면 str 값은 'xe5x93x88xe5x93x88'(하하의 utf-8 인코딩)

b. 파일 형식이 gbk이면 str 값은 'xb9xfexb9xfe'(하하 gbk 인코딩)입니다.

첫 번째 섹션에서 언급했듯이 Python의 문자열은 단지 바이트 배열이므로 a 경우 b의 str이 gbk로 인코딩된 콘솔에 출력되면 왜곡된 문자로 표시됩니다: 鍝矚搱; 그리고 b의 ​​경우 str이 utf-8로 인코딩된 콘솔에 출력되면 왜곡된 문자가 표시됩니다. 문제가 무엇인가요? 아니요, 어쩌면 'xb9xfexb9xfe'가 utf-8을 사용하여 디코딩되어 표시되므로 비어 있을 수 있습니다. >_<

파일 형식에 대해 이야기한 후 인코딩 문의 역할에 대해 이야기해 보겠습니다. 각 파일의 상단에는 #coding=gbk와 같은 문을 사용하여 인코딩을 선언하지만, 이 말은 무슨 소용이 있나요? 지금까지는 세 가지 기능이 있다고 생각합니다.

은 비ASCII 인코딩이 소스 파일에 나타날 것이라고 선언합니다. 일반적으로 고급에서는

IDE에서, IDE는 사용자가 지정한 인코딩 형식으로 파일 형식을 저장합니다.

소스 코드에서 u'ha'와 같은 선언에 대해 'ha'를 유니코드로 디코딩하는 데 사용되는 인코딩 형식을 결정하는 것도 혼란스러운 부분입니다.

#coding:gbk


ss = u'haha'

print repr(ss)

print 'ss:% s' % ss

이 코드를 utf-8 텍스트로 저장하고 실행해 보세요. 어떤 결과가 나올 것 같나요? 모든 사람의 첫인상은 다음과 같습니다.

u'u54c8u54c8'

ss: 하하

하지만 실제 출력은 다음과 같습니다.

u'u935du581du6431 '

ss:鍝埚搱

이때 인코딩문이 문제를 일으키네요. 다음 단계:

1) 'haha' 인코딩을 가져옵니다: 파일 인코딩 형식에 따라 결정됩니다. 'xe5x93x88xe5x93x88'(haha의 utf-8 인코딩 형식)

2) 유니코드 인코딩으로 변환할 때, 이 변환 과정에서 'xe5x93x88xe5x93x88'의 디코딩은 utf-8로 디코딩되지 않고 GBK에 따라 Decode 'xe5x93x88xe5x93x88' 선언에 지정된 GBK 인코딩으로 결과는 "鍝"입니다.獟搐" 에서 이 세 문자의 유니코드 인코딩은 u'u935du581du6431'입니다. 이는 print repr(ss)가 u'u935du581du6431'을 출력하는 이유를 설명할 수 있습니다.

알겠습니다. 약간 혼란스럽습니다. 다음 예를 분석해 보겠습니다.

#-*-coding:utf-8 -*-

ss = u'haha'

print repr(ss)

print 'ss:%s' % ss

이번 예제를 GBK 인코딩으로 저장하면 결과는 다음과 같습니다.

UnicodeDecodeError: 'utf8' 코덱은 위치 0의 바이트 0xb9를 디코딩할 수 없습니다: 예기치 않은 코드 바이트

여기에 왜 utf8 디코딩 오류가 있습니까? 앞의 예를 생각해보면 변환의 첫 번째 단계에서는 파일 인코딩이 GBK이므로 얻어지는 인코딩은 '하하'이며, 두 번째 단계를 수행하면 변환할 때 GBK 인코딩이 'xb9xfexb9xfe'입니다. 유니코드의 경우 'xb9xfexb9xfe'를 디코딩하면 UTF8이 사용되는데, utf-8 인코딩 테이블을 확인해보면 utf8 인코딩 테이블에는 전혀 존재하지 않는 것을 알 수 있습니다(UTF-8에 대한 설명은 참고) 문자 인코딩 참고 사항: ASCII, UTF-8, UNICODE)에 적용되므로 위 오류가 보고됩니다.


파이썬 중국어 왜곡 문제에 대한 더 심층적인 분석과 관련 글은 PHP 중국어 홈페이지를 주목해주세요!


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿