[python] 수정 방법 :“UnicodeDecodeError : ‘ascii’코덱이 바이트를 디코딩 할 수 없습니다 ‘
as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!
고치는 방법?
다른 파이썬 기반 정적 블로그 앱에서 중국어 게시물을 성공적으로 게시 할 수 있습니다. 이 응용 프로그램과 같은 : http://github.com/vrypan/bucket3 . 내 사이트 http://bc3.brite.biz/ 에서 중국어 게시물을 성공적으로 게시 할 수 있습니다.
답변
tl; dr / 빠른 수정
- Willy Nilly를 디코딩 / 인코딩하지 마십시오
- 문자열이 UTF-8로 인코딩되어 있다고 가정하지 마십시오
- 코드에서 가능한 빨리 문자열을 유니 코드 문자열로 변환하십시오.
- 로케일을 수정하십시오. Python 3.6에서 UnicodeDecodeError를 해결하는 방법?
- 빠른
reload
해킹 을 사용하려는 유혹을받지 마십시오
Python 2.x의 유니 코드 젠-긴 버전
소스를 보지 않으면 근본 원인을 알기가 어렵 기 때문에 일반적으로 말해야합니다.
UnicodeDecodeError: 'ascii' codec can't decode byte
일반적으로 Python 2.x를 변환하려고 할 때 발생합니다. str
원래 문자열의 인코딩을 지정하지 않고 비 ASCII가 포함 를 유니 코드 문자열 합니다.
간단히 말해서, 유니 코드 문자열은 인코딩을 포함하지 않는 완전히 분리 된 유형의 파이썬 문자열입니다. 유니 코드 포인트 코드 만 보유 하므로 전체 스펙트럼에서 유니 코드 포인트를 보유 할 수 있습니다. 인코딩 된 텍스트 스트링을 포함 베이트 UTF-8, UTF-16, ISO-8895-1, GBK, 등의 Big5 문자열이 유니 코드 디코딩 및 문자열로 인코딩 Unicodes . 파일과 텍스트 데이터는 항상 인코딩 된 문자열로 전송됩니다.
Markdown 모듈 작성자 unicode()
는 나머지 코드의 품질 게이트로 예외 (예외가 발생한 경우)를 사용합니다. ASCII를 변환하거나 기존 유니 코드 문자열을 새 유니 코드 문자열로 다시 랩핑합니다. Markdown 작성자는 들어오는 문자열의 인코딩을 알 수 없으므로 Markdown으로 전달하기 전에 문자열을 유니 코드 문자열로 디코딩해야합니다.
문자열에 u
접두사를 사용하여 코드에서 유니 코드 문자열을 선언 할 수 있습니다 . 예 :
>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
유니 코드 문자열은 파일, 데이터베이스 및 네트워크 모듈에서 올 수도 있습니다. 이 경우 인코딩에 대해 걱정할 필요가 없습니다.
잡았다
str
명시 적으로 호출하지 않아도 유니 코드 에서 유니 코드로 변환 할 수 있습니다 unicode()
.
다음과 같은 시나리오에서는 UnicodeDecodeError
예외가 발생합니다.
# Explicit conversion without encoding
unicode('€')
# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')
# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'
# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'
예
다음 다이어그램 café
에서 터미널 유형에 따라 단어 가 “UTF-8″또는 “Cp1252″인코딩으로 인코딩 된 방식을 볼 수 있습니다. 두 예에서 모두 caf
규칙적인 ASCII입니다. UTF-8에서는 é
2 바이트를 사용하여 인코딩됩니다. “Cp1252″에서 é는 0xE9입니다 (이는 유니 코드 포인트 값이기도합니다 (우연의 일치가 아님)). 올바른 decode()
것이 호출되고 Python 유니 코드로 변환이 성공합니다.
이 다이어그램에서 decode()
로 호출됩니다 ascii
( unicode()
인코딩없이 호출하는 것과 동일 ). ASCII는보다 큰 바이트를 포함 할 수 없으므로 예외 0x7F
가 UnicodeDecodeError
발생합니다.
유니 코드 샌드위치
들어오는 모든 데이터를 유니 코드 문자열로 디코딩하고 유니 코드로 작업 한 다음 str
나가는 길로 인코딩하는 코드에 유니 코드 샌드위치를 형성하는 것이 좋습니다 . 이렇게하면 코드 중간에 문자열 인코딩을 걱정할 필요가 없습니다.
입력 / 디코딩
소스 코드
비 ASCII를 소스 코드에 구워야하는 경우 문자열 앞에 접두사를 붙여 유니 코드 문자열을 만드십시오 u
. 예 :
u'Zürich'
파이썬이 소스 코드를 해독 할 수있게하려면 파일의 실제 인코딩과 일치하도록 인코딩 헤더를 추가해야합니다. 예를 들어 파일이 ‘UTF-8’로 인코딩 된 경우 다음을 사용합니다.
# encoding: utf-8
소스 코드 에 비 ASCII가있는 경우에만 필요 합니다 .
파일
일반적으로 비 ASCII 데이터는 파일에서 수신됩니다. 이 io
모듈은 지정된을 사용하여 파일을 즉시 디코딩하는 TextWrapper를 제공합니다 encoding
. 파일에 올바른 인코딩을 사용해야합니다. 쉽게 추측 할 수 없습니다. 예를 들어, UTF-8 파일의 경우 :
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
my_unicode_string = my_file.read()
my_unicode_string
그런 다음 Markdown으로 전달하기에 적합합니다. 경우 UnicodeDecodeError
로부터 read()
라인, 그때는 아마 잘못된 인코딩 값을 사용했습니다.
CSV 파일
Python 2.7 CSV 모듈은 비 ASCII 문자를 지원하지 않습니다. 그러나 https://pypi.python.org/pypi/backports.csv의 도움이 필요 합니다.
위와 같이 사용하지만 열린 파일을 전달하십시오.
from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
for row in csv.reader(my_file):
yield row
데이터베이스
대부분의 Python 데이터베이스 드라이버는 유니 코드로 데이터를 반환 할 수 있지만 일반적으로 약간의 구성이 필요합니다. SQL 쿼리에는 항상 유니 코드 문자열을 사용하십시오.
MySQL
연결 문자열에서 다음을 추가하십시오.
charset='utf8',
use_unicode=True
예 :
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL
더하다:
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
HTTP
웹 페이지는 거의 모든 인코딩으로 인코딩 될 수 있습니다. Content-type
헤더는 포함해야 charset
부호화 암시하는 필드. 그런 다음이 값에 대해 내용을 수동으로 디코딩 할 수 있습니다. 또는 Python-Requests 는에서 유니 코드를 반환합니다 response.text
.
수동으로
문자열을 수동으로 디코딩해야하는 경우 적절한 인코딩이있는 my_string.decode(encoding)
곳 encoding
이면됩니다. Python 2.x 지원 코덱은 다음과 같습니다. Standard Encodings . 다시 말하지만, UnicodeDecodeError
인코딩이 잘못되었을 수 있습니다.
샌드위치 고기
일반적인 str과 마찬가지로 유니 코드로 작업하십시오.
산출
표준 출력 / 인쇄
print
stdout 스트림을 통해 씁니다. 파이썬은 유니 코드가 콘솔의 인코딩으로 인코딩되도록 stdout에서 인코더를 구성하려고 시도합니다. 예를 들어, Linux 쉘 locale
이 en_GB.UTF-8
인 경우 출력은로 인코딩됩니다 UTF-8
. Windows에서는 8 비트 코드 페이지로 제한됩니다.
손상된 로캘과 같이 잘못 구성된 콘솔은 예기치 않은 인쇄 오류로 이어질 수 있습니다. PYTHONIOENCODING
환경 변수는 stdout 인코딩을 강제 할 수 있습니다.
파일
입력과 마찬가지로 io.open
유니 코드를 인코딩 된 바이트 문자열로 투명하게 변환하는 데 사용할 수 있습니다.
데이터 베이스
동일한 읽기 구성으로 유니 코드를 직접 작성할 수 있습니다.
파이썬 3
Python 3은 더 이상 Python 2.x보다 유니 코드를 사용할 수 없지만 주제에 대해 약간 덜 혼동됩니다. 예를 들어 일반 str
은 이제 유니 코드 문자열이고 이전 str
은 이제 bytes
입니다.
기본 인코딩은 UTF-8이므로 .decode()
인코딩하지 않고 바이트 문자열을 사용하면 Python 3은 UTF-8 인코딩을 사용합니다. 이것은 아마도 사람들의 유니 코드 문제의 50 %를 해결합니다.
또한 open()
기본적으로 텍스트 모드에서 작동하므로 디코딩 된 str
(유니 코드 것)을 반환합니다 . 인코딩은 로케일에서 파생되며, Un * x 시스템의 UTF-8 또는 Windows 상자의 windows-1251와 같은 8 비트 코드 페이지입니다.
왜 사용하지 않아야 하는가 sys.setdefaultencoding('utf8')
reload
문제를 가리고 Python 3.x 로의 마이그레이션을 방해 하는 불쾌한 해킹입니다 (사용해야하는 이유가 있습니다 ). 문제를 이해하고 근본 원인을 해결하고 유니 코드 선을 즐기십시오. py 스크립트에서 sys.setdefaultencoding ( “utf-8”)을 사용하지 않아야하는 이유를 참조하십시오 . 자세한 내용은
답변
마침내 나는 그것을 얻었다 :
as3:/usr/local/lib/python2.7/site-packages# cat sitecustomize.py
# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
내가 체크해 볼게:
as3:~/ngokevin-site# python
Python 2.7.6 (default, Dec 6 2013, 14:49:02)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.getdefaultencoding()
'utf8'
>>>
위의 python의 기본 인코딩은입니다 utf8
. 그렇다면 오류는 더 이상 없습니다.
답변
이것은 고전적인 “유니 코드 문제”입니다. 나는 이것을 설명하는 것이 무슨 일인지 완전히 설명하기 위해 StackOverflow 답변의 범위를 벗어난 것이라고 생각합니다.
여기에 잘 설명되어 있습니다 .
간단히 요약하면 바이트 문자열로 해석되는 것을 유니 코드 문자로 디코딩해야하는 것으로 전달했지만 기본 코덱 (ascii)은 실패합니다.
이것을 피하기위한 조언을 해주겠다고 지시 한 프레젠테이션. 코드를 “유니 코드 샌드위치”로 만드십시오. 파이썬 2에서는 from __future__ import unicode_literals
도움을 사용 합니다.
업데이트 : 코드를 수정하는 방법 :
OK – 변수 “source”에 약간의 바이트가 있습니다. 귀하의 질문에 그들이 어떻게 들어 왔는지는 분명하지 않습니다. 아마도 웹 양식에서 읽을 수 있습니까? 어쨌든 그들은 ascii로 인코딩되지 않지만 파이썬은 그것들을 가정하여 유니 코드로 변환하려고합니다. 인코딩이 무엇인지 명시 적으로 알려 주어야합니다. 이것은 인코딩이 무엇인지 알아야 한다는 것을 의미합니다 ! 항상 쉬운 것은 아니며이 문자열의 출처에 전적으로 달려 있습니다. UTF-8과 같은 일반적인 인코딩을 실험 해 볼 수 있습니다. unicode ()에게 두 번째 매개 변수로 인코딩을 알려줍니다.
source = unicode(source, 'utf-8')
답변
경우에 따라 기본 인코딩 ( print sys.getdefaultencoding()
) 을 확인 하면 ASCII를 사용하고 있음을 반환합니다. UTF-8로 변경하면 변수의 내용에 따라 작동하지 않습니다. 다른 방법을 찾았습니다.
import sys
reload(sys)
sys.setdefaultencoding('Cp1252')
답변
다음 오류 메시지를 해결하기 위해 검색했습니다.
unicodedecodeerror : ‘ascii’코덱이 5454 위치에서 바이트 0xe2를 디코딩 할 수 없습니다 : 서 수가 범위 내에 있지 않습니다 (128)
마침내 ‘encoding’을 지정하여 수정했습니다.
f = open('../glove/glove.6B.100d.txt', encoding="utf-8")
그것이 당신을 도울 수 있기를 바랍니다.
답변
"UnicodeDecodeError: 'ascii' codec can't decode byte"
이 오류의 원인 : input_string은 유니 코드 여야하지만 str이 제공되었습니다.
"TypeError: Decoding Unicode is not supported"
이 오류의 원인 : 유니 코드 input_string을 유니 코드로 변환하려고합니다.
따라서 먼저 input_string이 있는지 확인하고 str
필요한 경우 유니 코드로 변환하십시오.
if isinstance(input_string, str):
input_string = unicode(input_string, 'utf-8')
둘째, 위의 유형 만 변경하지만 ASCII가 아닌 문자는 제거하지 않습니다. ASCII가 아닌 문자를 제거하려는 경우 :
if isinstance(input_string, str):
input_string = input_string.decode('ascii', 'ignore').encode('ascii') #note: this removes the character and encodes back to string.
elif isinstance(input_string, unicode):
input_string = input_string.encode('ascii', 'ignore')
답변
나는 항상 유니 코드로 변환하는 것이 가장 좋다는 것을 알지만 실제로는 모든 인수를 확인하고 문자열 처리 형식을 포함하는 모든 함수 및 메소드로 변환해야하기 때문에 달성하기가 어렵습니다.
그래서 두 입력 중 하나에서 유니 코드 또는 바이트 문자열을 보장하기 위해 다음과 같은 접근법을 생각해 냈습니다. 간단히 말해 다음 람다를 포함하여 사용 하십시오.
# guarantee unicode string
_u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t
_uu = lambda *tt: tuple(_u(t) for t in tt)
# guarantee byte string in UTF8 encoding
_u8 = lambda t: t.encode('UTF-8', 'replace') if isinstance(t, unicode) else t
_uu8 = lambda *tt: tuple(_u8(t) for t in tt)
예 :
text='Some string with codes > 127, like Zürich'
utext=u'Some string with codes > 127, like Zürich'
print "==> with _u, _uu"
print _u(text), type(_u(text))
print _u(utext), type(_u(utext))
print _uu(text, utext), type(_uu(text, utext))
print "==> with u8, uu8"
print _u8(text), type(_u8(text))
print _u8(utext), type(_u8(utext))
print _uu8(text, utext), type(_uu8(text, utext))
# with % formatting, always use _u() and _uu()
print "Some unknown input %s" % _u(text)
print "Multiple inputs %s, %s" % _uu(text, text)
# but with string.format be sure to always work with unicode strings
print u"Also works with formats: {}".format(_u(text))
print u"Also works with formats: {},{}".format(*_uu(text, text))
# ... or use _u8 and _uu8, because string.format expects byte strings
print "Also works with formats: {}".format(_u8(text))
print "Also works with formats: {},{}".format(*_uu8(text, text))