> 백엔드 개발 > 파이썬 튜토리얼 > python2.x 기본 인코딩 문제 해결 방법

python2.x 기본 인코딩 문제 해결 방법

高洛峰
풀어 주다: 2017-03-21 13:17:59
원래의
1617명이 탐색했습니다.

파이썬2.x에서 중국어를 처리하는 것은 골치 아픈 일입니다. 인터넷에서 이 분야에 쓰여진 글들은 고르지 못한 테스트를 거쳤고, 항상 실수가 있기 때문에 제가 직접 글을 요약할 계획입니다.

앞으로도 공부하면서 이 블로그도 계속 수정하겠습니다.

이 기사에서는 utf-8이 무엇인지, 유니코드가 무엇인지, 이들 사이의 관계가 무엇인지 등 인코딩과 관련된 기본 지식이 이미 있다고 가정합니다.
str 및 바이트코드

우선 유니코드에 대해서는 전혀 이야기하지 말자.

s = "人生苦短"
로그인 후 복사

s는 바이트코드를 저장하는 문자열입니다. 그렇다면 이 바이트코드의 형식은 무엇입니까?

이 코드가 인터프리터에 입력되면 이 s의 형식은 인터프리터의 인코딩 형식입니다. Windows cmd의 경우 gbk입니다.

코드를 저장하고 실행하면, 예를 들어 utf-8로 저장되어 있으면 인터프리터가 이 프로그램을 로드하면 s가 utf-8 인코딩으로 초기화됩니다.
유니코드 및 str

우리는 유니코드가 코딩 표준이라는 것을 알고 있으며 구체적인 구현 표준은 utf-8, utf-16, gbk...

Python은 내부적으로 2바이트를 사용하여 유니코드를 저장합니다. str 대신 유니코드 객체를 사용하면 유니코드가 크로스 플랫폼에 편리하다는 장점이 있습니다.

유니코드는 다음 두 가지 방법으로 정의할 수 있습니다.

s1 = u"人生苦短"
s2 = unicode("人生苦短", "utf-8")
로그인 후 복사

인코딩 및 디코드

파이썬의 인코딩 및 디코딩은 다음과 같습니다.

python2.x 默认编码问题解决方法

다음과 같은 코드를 작성할 수 있습니다.

# -*- coding:utf-8 -*-
su = "人生苦短"
# : su是一个utf-8格式的字节串
u = s.decode("utf-8")
# : s被解码为unicode对象,赋给u
sg = u.encode("gbk")
# : u被编码为gbk格式的字节串,赋给sg
print sg
# 打印sg
로그인 후 복사

그러나 현실은 이보다 더 복잡합니다. 예를 들어 다음 코드를 살펴보세요.

아아아아

보세요! str도 인코딩할 수 있습니다. (사실 유니코드 객체도 디코딩할 수 있지만 별 의미는 없습니다.)

왜 이것이 가능합니까? 위 그림에서 인코딩 과정의 화살표를 보면 원리를 생각해볼 수 있는데, str을 인코딩할 때 먼저 기본 인코딩을 사용하여 자신을 유니코드로 디코딩한 다음, 지정한 인코딩으로 유니코드를 인코딩합니다.

이것은 python2에서 중국어를 처리할 때 대부분의 오류가 발생하는 이유입니다. >

s = "人生苦短"
s.encode('gbk')
로그인 후 복사

위 코드는

오류 메시지
오류를 보고합니다: UnicodeDecodeError: 'ascii' codec can 바이트를 디코딩하지 않습니다...

기본 인코딩을 지정하지 않았기 때문에 실제로 다음과 같은 작업을 수행합니다.

# -*- coding: utf-8 -*-
s = "人生苦短"
s.encode('gbk')
로그인 후 복사

기본 인코딩 설정

기본 인코딩을 설정하는 코드는 다음과 같습니다.

# -*- coding: utf-8 -*-
s = "人生苦短"
s.decode('ascii').encode('gbk')
로그인 후 복사
파이썬에서 인코딩과 디코딩을 하는 경우, 인코딩 방법을 지정하지 않으면 파이썬에서는 기본 인코딩을 사용하게 됩니다.

예를 들어 이전 섹션의 예에서 str이 다른 형식으로 인코딩되면 defaultencoding이 사용됩니다.

reload(sys)
sys.setdefaultencoding('utf-8')
로그인 후 복사

또 다른 예를 들어, str을 사용하여 유니코드 객체를 생성할 때 이 str의 인코딩 형식을 지정하지 않으면 프로그램은 기본 인코딩도 사용합니다.

s.encode("utf-8") 等价于 s.decode(defaultencoding).encode("utf-8")
로그인 후 복사

기본 인코딩인 ascii는 많은 오류의 원인이므로 초기에 기본 인코딩을 설정하는 것이 좋은 습관입니다.

파일 헤더는 인코딩의 역할을 선언합니다.

파이썬 파일의 헤더 부분을 설명해 주신 블로그에 감사드립니다. 상위:# -*- 코딩: utf-8 -*- 현재는 세 가지 기능이 있는 것으로 보입니다.

코드에 중국어

주석

이 있는 경우 다음 명령문이 필요합니다.

고급

편집기(예: 내 emacs)는 헤더를 기반으로 선언합니다. 이를 코드 파일의 형식으로 사용하십시오. 프로그램은 유니코드 객체와 같은 헤더 선언을 통해 "인생은 짧다"를 디코딩하고 초기화합니다. (따라서 헤더 선언과 코드의 저장 형식이 일치해야 합니다.)
소개 요청 라이브러리

requests는 크롤러를 작성하고 서버 응답 데이터를 테스트할 때 자주 사용되는 매우 실용적인 Python HTTP 클라이언트 라이브러리입니다. Request 객체는 서버에 액세스한 후 Response 객체를 반환합니다. 이 객체는 반환된 Http 응답 바이트코드를 content 속성에 저장합니다.

그런데 다른 속성 텍스트에 접근하면 유니코드 객체가 반환되고 여기서 잘못된 문자가 자주 발생합니다.

Response 객체는 다른 속성 인코딩을 통해 바이트코드를 유니코드로 인코딩하기 때문에 이 인코딩 속성은 실제로 응답 자체에서 추측됩니다.

官方文档:

text
Content of the response, in unicode.

If Response.encoding is None, encoding will be guessed using chardet.

The encoding of the response content is determined based solely on HTTP headers, following RFC 2616 to the letter. If you can take advantage of non-HTTP knowledge to make a better guess at the encoding, you should set r.encoding appropriately before accessing this property.

所以要么你直接使用content(字节码),要么记得把encoding设置正确,比如我获取了一段gbk编码的网页,就需要以下方法才能得到正确的unicode。

import requests
url = "http://xxx.xxx.xxx"
response = requests.get(url)
response.encoding = 'gbk'
  
print response.text
로그인 후 복사


如果是早期的我写博客,那么我一定会写这样的例子:不仅仅要原理,更要使用方法!

如果现在的文件编码为gbk,然后文件头为:# -*- coding: utf-8 -*-,再将默认编码设置为xxx,那么如下程序的结果会是……

这就类似于,当年学c的时候,用各种优先级,结合性,指针来展示自己水平的代码。

实际上这些根本就不实用,谁会在真正的工作中写这样的代码呢?我在这里想谈谈实用的处理中文的python方法。

基本设置

主动设置defaultencoding。(默认的是ascii)

代码文件的保存格式要与文件头部的# coding:xxx一致

如果是中文,程序内部尽量使用unicode,而不用str

关于打印

你在打印str的时候,实际就是直接将字节流发送给shell。如果你的字节流编码格式与shell的编码格式不相同,就会乱码。

而你在打印unicode的时候,系统自动将其编码为shell的编码格式,是不会出现乱码的。

程序内外要统一

如果说程序内部要保证只用unicode,那么在从外部读如字节流的时候,一定要将这些字节流转化为unicode,在后面的代码中去处理unicode,而不是str。

with open("test") as f:
 for i in f:
 # 将读入的utf-8字节流进行解码
 u = i.decode('utf-8')
 ....
로그인 후 복사

如果把连接程序内外的这段数据流比喻成通道的的话,那么与其将通道开为字节流,读入后进行解码,不如直接将通道开为unicode的。

# 使用codecs直接开unicode通道
file = codecs.open("test", "r", "utf-8")
for i in file:
 print type(i)
 # i的类型是unicode的
로그인 후 복사

所以python处理中文编码问题的关键是你要清晰的明白,自己在干什么,打算读入什么格式的编码,声明的的这些字节是什么格式的,str到unicode是如何转换的,str的一种编码到另一种编码又是如何进行的。 还有,你不能把问题变得混乱,要自己主动去维护一种统一。

 

python 3和2很大区别就是python本身改为默认用unicode编码。

字符串不再区分"abc"和u"abc", 字符串"abc"默认就是unicode,不再代表本地编码、

由于有这种内部编码,像c#和java类似,再没有必要在语言环境内做类似设置编码,比如“sys.setdefaultencoding”;

也因此也python 3的代码和包管理上打破了和2.x的兼容。2.x的扩展包要适应这种情况改写。

另一个问题是语言环境内只有unicode怎么输出gbk之类的本地编码。


1.如果你在Python中进行编码和解码的时候,不指定编码方式,那么python就会使用defaultencoding。 而python2.x的的defaultencoding是ascii,

这也就是大多数python编码报错:“UnicodeDecodeError: 'ascii' codec can't decode byte ......”的原因。

 

2.关于头部的# coding:utf-8,有以下几个作用 2.1如果代码中有中文注释,就需要此声明 2.2比较高级的编辑器(比如我的emacs),会根据头部声明,将此作为代码文件的格式。 2.3程序会通过头部声明,解码初始化 u"人生苦短",这样的unicode对象,(所以头部声明和代码的存储格式要一致)

python2.7以后不用setdefaultencoding了,这两个是没有区别的


这两个作用不一样, 1. # coding:utf-8 作用是定义源代码的编码. 如果没有定义, 此源码中是不可以包含中文字符串的. PEP 0263 -- Defining Python Source Code Encodings https://www.python.org/dev/peps/pep-0263/ 2. sys.getdefaultencoding() 是设置默认的string的编码格式

答按惯例都在(序列化)输出时才转换成本地编码。

위 내용은 python2.x 기본 인코딩 문제 해결 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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