Python- 'ascii'코덱이 바이트를 디코딩 할 수 없습니다.


119

정말 혼란 스러워요. 인코딩을 시도했지만 오류가 발생했습니다 can't decode....

>>> "你好".encode("utf8")
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)

문자열에 "u"접두사가있는 오류를 피하는 방법을 알고 있습니다. 인코딩이 호출되었을 때 오류가 "디코딩 할 수 없음"인 이유가 궁금합니다. 파이썬은 내부적으로 무엇을하고 있습니까?

답변:


167
"你好".encode('utf-8')

encode유니 코드 객체를 객체로 변환 string합니다. 그러나 여기에서는 string객체 에 대해 호출했습니다 (U가 없기 때문에). 그래서 파이썬은 먼저를 객체 로 변환해야 string합니다 unicode. 그래서 그것은

"你好".decode().encode('utf-8')

그러나 문자열이 유효한 ASCII가 아니기 때문에 디코딩이 실패합니다. 그렇기 때문에 해독 할 수 없다는 불만이 있습니다.


50
그렇다면 해결책은 무엇입니까? 특히 문자열 리터럴이 없으면 문자열 개체 만 있습니다.
존 Tirsen

2
@JonTirsen, 문자열 객체를 인코딩해서는 안됩니다. 문자열 개체가 이미 인코딩되었습니다. 인코딩을 변경해야하는 경우이를 유니 코드 문자열로 디코딩 한 다음 원하는 인코딩으로 인코딩해야합니다.
Winston Ewert 2013 년

20
그래서 당신이 할 수있는 위에서 명확하게 명시합니다"你好".decode('utf-8').encode('utf-8')
deinonychusaur

5
@WinstonEwert 내가 혼란 스러웠던 것 같아요. 인코딩 사업은 나를 영원히 혼란스럽게 만드는 경향이 있습니다. 내 혼란은 입력이 문자열인지 유니 코드 문자열인지 그리고 어떤 인코딩이 있는지 알지 못하는 내 문제에서 비롯된 것 같습니다.
deinonychusaur jul.

@deinonychusaur, 예 ... 알겠습니다.
Winston Ewert 2013

53

항상 유니 코드에서 바이트로 인코딩 합니다.
이 방향으로 인코딩을 선택하게 됩니다.

>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好

다른 방법은 바이트에서 유니 코드로 디코딩하는 것입니다.
이 방향 에서 인코딩이 무엇인지 알아야합니다 .

>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好

이 점은 충분히 강조 할 수 없습니다. 유니 코드 "두더지 잡기"를하지 않으려면 데이터 수준에서 무슨 일이 일어나고 있는지 이해하는 것이 중요합니다. 여기에서는 다른 방법으로 설명합니다.

  • 유니 코드 객체는 이미 디코딩되어 있으므로 절대 호출하고 싶지 않습니다 decode.
  • 바이트 문자열 객체는 이미 인코딩되어 있으므로 호출하고 싶지 않습니다 encode.

이제 .encode바이트 문자열 을 볼 때 Python 2는 먼저 암시 적으로 텍스트 ( unicode객체) 로 변환하려고합니다 . 마찬가지로, .decode유니 코드 문자열을 보면 Python 2는 암시 적으로이를 바이트 ( str객체) 로 변환하려고합니다 .

이러한 암시 적 변환 은를 호출했을 때 얻을 수있는 이유 입니다. 인코딩은 일반적으로 유형의 매개 변수를 허용하기 때문입니다 . 매개 변수를 수신 할 때 다른 인코딩으로 다시 인코딩하기 전에 유형의 객체에 대한 암시 적 디코딩이 있습니다. 이 변환은 기본 'ascii'디코더 †를 선택 하여 인코더 내부의 디코딩 오류를 제공합니다.UnicodeDecodeErrorencodeunicodestrunicode

사실, 파이썬 3 방법에 str.decodebytes.encode도 존재하지 않는다. 이들의 제거는 이러한 일반적인 혼란을 피하기위한 [논란의 여지가있는] 시도였습니다.

... 또는 코딩이 sys.getdefaultencoding()언급하는 모든 것; 보통 이것은 'ascii'입니다.


그렇다면 파이썬이 인코딩하기 전에 바이트 문자열을 디코딩한다는 의미입니까?
thoslin

@thoslin 정확히, 더 자세한 내용을 추가했습니다.
2014 년

_은 무엇이며 인쇄 문에 괄호가없는 이유는 무엇입니까?
NoBugs 2017 년

1
@NoBugs 1. REPL에서 _이것은 python-2.x 질문이기 때문에 이전 값 2를 참조합니다.
wim

40

당신은 이것을 시도 할 수 있습니다

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

또는

다음을 시도해 볼 수도 있습니다.

.py 파일 상단에 다음 줄을 추가하십시오.

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

8

Python <3을 사용하는 경우 문자열 리터럴이 유니 코드u 라는 것을 인터프리터에게 다음 접두사 로 알려야합니다 .

Python 2.7.2 (default, Jan 14 2012, 23:14:09) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
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)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'

더 읽을 거리 : Unicode HOWTO .


4
문자열을 인코딩하는 경우 디코딩 오류가 발생하는 이유는 무엇입니까?
MxLDevs 2010 년

3

u"你好".encode('utf8')유니 코드 문자열을 인코딩하는 데 사용 합니다. 그러나을 표현 "你好"하려면 디코딩해야합니다. 처럼:

"你好".decode("utf8")

원하는 것을 얻을 수 있습니다. 인코딩 및 디코딩에 대해 자세히 알아봐야 할 것입니다.


3

유니 코드를 다루는 경우, 가끔은 대신 encode('utf-8')특수 문자를 무시할 수도 있습니다.

"你好".encode('ascii','ignore')

또는 something.decode('unicode_escape').encode('ascii','ignore')여기에 제안 된대로 .

이 예에서는 특히 유용하지 않지만 일부 특수 문자를 변환 할 수없는 다른 시나리오에서는 더 잘 작동 할 수 있습니다.

또는을 사용하여 특정 문자를 대체하는replace() 것을 고려할 수 있습니다 .


1

Linux 또는 유사한 시스템 (BSD, Mac에 대해 확실하지 않음)의 쉘에서 파이썬 인터프리터를 시작하는 경우 쉘의 기본 인코딩도 확인해야합니다.

locale charmap(파이썬 인터프리터가 아닌) 쉘에서 호출 하면

[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

그렇지 않은 경우, 예를 들어

[user@host dir] $ locale charmap
ANSI_X3.4-1968
[user@host dir] $ 

파이썬은 (적어도 저와 같은 어떤 경우에는) 셸의 인코딩을 상속하고 유니 코드 문자를 인쇄 할 수 없습니다 (일부? 전부?). 파이썬의 자신의 기본 당신이 볼 것을 인코딩을 통해 제어 sys.getdefaultencoding()sys.setdefaultencoding()무시이 경우입니다.

이 문제가 발견되면 다음 방법으로 해결할 수 있습니다.

[user@host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

(또는 en_EN 대신 원하는 키맵을 선택하십시오.) 또한 편집 /etc/locale.conf(또는 시스템의 로케일 정의를 관리하는 파일)을 수정할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.