질문자 :Homunculus Reticulli
다른 웹 페이지(다른 사이트)에서 가져온 텍스트의 유니코드 문자를 처리하는 데 문제가 있습니다. 저는 BeautifulSoup을 사용하고 있습니다.
문제는 오류가 항상 재현 가능한 것은 아니라는 것입니다. 때로는 일부 페이지에서 작동하고 때로는 UnicodeEncodeError
를 던져 방해합니다. 생각할 수 있는 모든 것을 시도해 보았지만 유니코드 관련 오류가 발생하지 않고 일관되게 작동하는 것을 찾지 못했습니다.
문제를 일으키는 코드 섹션 중 하나는 다음과 같습니다.
agent_telno = agent.find('div', 'agent_contact_number') agent_telno = '' if agent_telno is None else agent_telno.contents[0] p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
다음은 위의 스니펫이 실행될 때 일부 문자열에서 생성된 스택 추적입니다.
Traceback (most recent call last): File "foobar.py", line 792, in <module> p.agent_info = str(agent_contact + ' ' + agent_telno).strip() UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)
나는 이것이 일부 페이지(또는 보다 구체적으로 일부 사이트의 페이지)가 인코딩될 수 있고 다른 페이지는 인코딩되지 않을 수 있기 때문이라고 생각합니다. 모든 사이트는 영국에 기반을 두고 있으며 영국 소비를 위한 데이터를 제공합니다. 따라서 영어가 아닌 다른 언어로 작성된 텍스트를 처리하거나 내부화와 관련된 문제가 없습니다.
누구든지 이 문제를 일관되게 해결할 수 있도록 이 문제를 해결하는 방법에 대한 아이디어가 있습니까?
파이썬 유니코드 HOWTO 를 읽어야 합니다. 이 오류는 첫 번째 예 입니다.
기본적으로 str
을 사용하여 유니코드에서 인코딩된 텍스트/바이트로 변환하는 것을 중지합니다.
.encode()
를 적절히 사용하여 문자열을 인코딩하십시오.
p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()
또는 완전히 유니코드로 작동합니다.
agf이것은 고전적인 파이썬 유니코드의 문제점입니다! 다음을 고려하세요:
a = u'bats\u00E0' print a => batsà
지금까지는 모두 좋았지만 str(a)를 호출하면 어떤 일이 발생하는지 봅시다.
str(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
오 딥, 그건 아무에게도 도움이되지 않을 것입니다! 오류를 수정하려면 .encode를 사용하여 명시적으로 바이트를 인코딩하고 파이썬에 사용할 코덱을 알려주세요.
a.encode('utf-8') => 'bats\xc3\xa0' print a.encode('utf-8') => batsà
끓이다\u00E0!
문제는 str()을 호출할 때 python이 기본 문자 인코딩을 사용하여 사용자가 제공한 바이트를 인코딩하려고 시도하고 인코딩한다는 것입니다. 귀하의 경우에는 유니코드 문자를 나타내는 경우가 있습니다. 문제를 해결하려면 .encode('whatever_unicode')를 사용하여 제공한 문자열을 처리하는 방법을 파이썬에 알려야 합니다. 대부분의 경우 utf-8을 사용하는 것이 좋습니다.
이 주제에 대한 훌륭한 설명은 Ned Batchelder의 PyCon 강연을 참조하십시오. http://nedbatchelder.com/text/unipain.html
Andbdrew다음과 같이 기호를 제거하고 문자열을 계속 문자열로 유지하는 우아한 방법을 찾았습니다.
yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')
무시 옵션을 사용하는 것은 여기에서 볼 수 있듯이(유니코드 변환) 사용하는 코드에서 유니코드(및 국제화) 지원을 자동으로 삭제하기 때문에 위험하다는 점을 알아두는 것이 중요합니다.
>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii') 'City: Malm'
Max Korolevsky글쎄, 나는 모든 것을 시도했지만 도움이되지 않았습니다. 인터넷 검색을 한 후에 다음과 같이 생각하고 도움이되었습니다. 파이썬 2.7이 사용 중입니다.
# encoding=utf8 import sys reload(sys) sys.setdefaultencoding('utf8')
Ashwin인쇄에 실패하는 미묘한 문제는 환경 변수를 잘못 설정하는 것입니다. 여기서 LC_ALL은 "C"로 설정됩니다. 데비안에서는 설정하는 것을 권장하지 않습니다: Debian wiki on Locale
$ echo $LANG en_US.utf8 $ echo $LC_ALL C $ python -c "print (u'voil\u00e0')" Traceback (most recent call last): File "<string>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128) $ export LC_ALL='en_US.utf8' $ python -c "print (u'voil\u00e0')" voilà $ unset LC_ALL $ python -c "print (u'voil\u00e0')" voilà
maxpolk문제는 유니코드 문자를 인쇄하려고 하지만 터미널이 지원하지 않는다는 것입니다.
이 문제를 해결하기 위해 language-pack-en
패키지를 설치해 볼 수 있습니다.
sudo apt-get install language-pack-en
지원되는 모든 패키지(Python 포함)에 대한 영어 번역 데이터 업데이트를 제공합니다. 필요한 경우 다른 언어 패키지를 설치합니다(인쇄하려는 문자에 따라 다름).
일부 Linux 배포판에서는 기본 영어 로케일이 제대로 설정되었는지 확인하기 위해 필요합니다(유니코드 문자가 쉘/터미널에서 처리될 수 있도록). 때로는 수동으로 구성하는 것보다 설치하는 것이 더 쉽습니다.
그런 다음 코드를 작성할 때 코드에서 올바른 인코딩을 사용하는지 확인하십시오.
예를 들어:
open(foo, encoding='utf-8')
그래도 문제가 지속되면 다음과 같이 시스템 구성을 다시 확인하십시오.
로케일 파일( /etc/default/locale
), 예를 들어
LANG="en_US.UTF-8" LC_ALL="en_US.UTF-8"
또는:
LC_ALL=C.UTF-8 LANG=C.UTF-8
쉘의 LANG
/ LC_CTYPE
다음을 통해 쉘이 지원하는 로케일을 확인하십시오.
locale -a | grep "UTF-8"
새로운 VM에서 문제와 솔루션을 시연합니다.
VM 초기화 및 프로비저닝(예 vagrant
사용):
vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
참조: 사용 가능한 Ubuntu 상자 . .
유니코드 문자 인쇄(예 ™
와 같은 상표 기호):
$ python -c 'print(u"\u2122");' Traceback (most recent call last): File "<string>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
이제 language-pack-en
설치합니다.
$ sudo apt-get -y install language-pack-en The following extra packages will be installed: language-pack-en-base Generating locales... en_GB.UTF-8... /usr/sbin/locale-gen: done Generation complete.
이제 문제가 해결되어야 합니다.
$ python -c 'print(u"\u2122");' ™
그렇지 않으면 다음 명령을 시도하십시오.
$ LC_ALL=C.UTF-8 python -c 'print(u"\u2122");' ™
kenorb실제로 대부분의 경우 해당 문자를 제거하는 것이 훨씬 간단하다는 것을 알았습니다.
s = mystring.decode('ascii', 'ignore')
Phil LaNasa나를 위해 효과가 있었던 것은 다음과 같습니다.
BeautifulSoup(html_text,from_encoding="utf-8")
이것이 누군가를 돕기를 바랍니다.
Animesh쉘에서:
다음 명령으로 지원되는 UTF-8 로케일을 찾으십시오.
locale -a | grep "UTF-8"
스크립트를 실행하기 전에 내보냅니다. 예:
export LC_ALL=$(locale -a | grep UTF-8)
또는 다음과 같이 수동으로:
export LC_ALL=C.UTF-8
특수 문자(예: ™
를 인쇄하여 테스트하십시오.
python -c 'print(u"\u2122");'
위의 우분투에서 테스트되었습니다.
kenorb다음은 소위 "경찰 아웃" 답변을 다시 설명합니다. 여기에서 목소리를 낸 항의에도 불구하고 귀찮은 문자/문자열을 단순히 버리는 것이 좋은 해결책인 상황이 있습니다.
def safeStr(obj): try: return str(obj) except UnicodeEncodeError: return obj.encode('ascii', 'ignore').decode('ascii') except: return ""
테스트:
if __name__ == '__main__': print safeStr( 1 ) print safeStr( "test" ) print u'98\xb0' print safeStr( u'98\xb0' )
결과:
1 test 98° 98
업데이트: 내 원래 답변은 Python 2용으로 작성되었습니다. Python 3의 경우 :
def safeStr(obj): try: return str(obj).encode('ascii', 'ignore').decode('ascii') except: return ""
참고: 남기고 싶다면 ?
"안전하지 않은" 유니코드 문자가 있는 표시기에서 오류 처리기에 대한 인코딩 호출에서 ignore
대신 replace
제안: 대신 이 함수의 이름을 toAscii
로 지정하시겠습니까? 그건 취향문제...
six
사용하는 보다 강력한 PY2/3 버전이 있습니다 replace
를 사용하기로 선택했으며 왼쪽 또는 오른쪽으로 말리는 멋진 유니코드 따옴표와 아포스트로피를 ASCII 세트의 일부인 간단한 수직 따옴표로 대체하기 위해 일부 문자 스왑을 사용했습니다. . 이러한 스왑을 직접 확장할 수 있습니다.
from six import PY2, iteritems CHAR_SWAP = { u'\u201c': u'"' , u'\u201D': u'"' , u'\u2018': u"'" , u'\u2019': u"'" } def toAscii( text ) : try: for k,v in iteritems( CHAR_SWAP ): text = text.replace(k,v) except: pass try: return str( text ) if PY2 else bytes( text, 'replace' ).decode('ascii') except UnicodeEncodeError: return text.encode('ascii', 'replace').decode('ascii') except: return "" if __name__ == '__main__': print( toAscii( u'testin\u2019' ) )
BuvinJ스크립트 시작 부분(또는 두 번째 줄)에 아래 줄을 추가합니다.
# -*- coding: utf-8 -*-
이것이 파이썬 소스 코드 인코딩의 정의입니다. PEP 263 에서 더 많은 정보를 얻을 수 있습니다.
Andriy Ivaneyko저는 항상 파이썬 파일의 처음 두 줄에 아래 코드를 넣습니다.
# -*- coding: utf-8 -*- from __future__ import unicode_literals
Pereira아아 이것은 적어도 Python 3에서 작동합니다 ...
파이썬 3
때로는 오류가 환경 변수에 있고 그렇게
import os import locale os.environ["PYTHONIOENCODING"] = "utf-8" myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8") ... print(myText.encode('utf-8', errors='ignore'))
여기서 오류는 인코딩에서 무시됩니다.
hhh간단한 도우미 기능은 여기 에서 찾을 수 있습니다.
def safe_unicode(obj, *args): """ return the unicode representation of obj """ try: return unicode(obj, *args) except UnicodeDecodeError: # obj is byte string ascii_text = str(obj).encode('string_escape') return unicode(ascii_text) def safe_str(obj): """ return the byte string representation of obj """ try: return str(obj) except UnicodeEncodeError: # obj is unicode return unicode(obj).encode('unicode_escape')
Parag Tyagi변수에 추가하십시오. encode('utf-8')
agent_contact.encode('utf-8')
Kairat Koibagarov방금 다음을 사용했습니다.
import unicodedata message = unicodedata.normalize("NFKD", message)
문서가 그것에 대해 말하는지 확인하십시오.
unicodedata.normalize(form, unistr) 유니코드 문자열 unistr에 대한 일반 형식 형식을 반환합니다. 형식에 유효한 값은 'NFC', 'NFKC', 'NFD' 및 'NFKD'입니다.
유니코드 표준은 표준 동등성 및 호환성 동등성의 정의를 기반으로 유니코드 문자열의 다양한 정규화 형식을 정의합니다. 유니코드에서는 여러 문자를 다양한 방식으로 표현할 수 있습니다. 예를 들어, 문자 U+00C7(LATIN CAPITAL LETTER C WITH CEDILLA)은 U+0043(LATIN CAPITAL LETTER C) U+0327(COMBINING CEDILLA) 시퀀스로 표현될 수도 있습니다.
각 문자에는 두 가지 정규형이 있습니다. 정규형 C와 정규형 D. 정규형 D(NFD)는 표준 분해라고도 하며 각 문자를 분해된 형태로 변환합니다. 정규형 C(NFC)는 먼저 표준 분해를 적용한 다음 미리 결합된 문자를 다시 구성합니다.
이 두 가지 형식 외에도 호환성 동등성을 기반으로 하는 두 가지 추가 정규 형식이 있습니다. 유니코드에서는 일반적으로 다른 문자와 통합되는 특정 문자가 지원됩니다. 예를 들어, U+2160(ROMAN NUMERAL ONE)은 U+0049(LATIN CAPITAL LETTER I)와 실제로 동일합니다. 그러나 기존 문자 집합(예: gb2312)과의 호환성을 위해 유니코드에서 지원됩니다.
일반 형식 KD(NFKD)는 호환성 분해를 적용합니다. 즉, 모든 호환성 문자를 해당 문자로 바꿉니다. 정규형 KC(NFKC)는 먼저 호환성 분해를 적용한 다음 표준 구성을 적용합니다.
두 개의 유니코드 문자열이 정규화되어 독자에게 동일하게 보이더라도 하나는 결합 문자를 갖고 다른 하나는 결합하지 않으면 동일하게 비교되지 않을 수 있습니다.
나를 위해 그것을 해결합니다. 간단하고 쉽습니다.
Drag0터미널을 열고 아래 명령을 실행하십시오.
export LC_ALL="en_US.UTF-8"
Hồ Ngọc Vượng아래 솔루션이 저에게 효과적이었습니다. 방금 추가했습니다.
유 "문자열"
(문자열을 유니코드로 나타냄) 내 문자열 앞에.
result_html = result.to_html(col_space=1, index=False, justify={'right'}) text = u""" <html> <body> <p> Hello all, <br> <br> Here's weekly summary report. Let me know if you have any questions. <br> <br> Data Summary <br> <br> <br> {0} </p> <p>Thanks,</p> <p>Data Team</p> </body></html> """.format(result_html)
Aravind Krishnakumar방금이 문제가 있었고 Google이 나를 여기로 안내 했으므로 여기에 일반적인 솔루션을 추가하기 만하면 이것이 저에게 효과적이었습니다.
# 'value' contains the problematic data unic = u'' unic += value value = unic
Ned의 프레젠테이션 을 읽은 후 이런 생각을 했습니다.
나는 이것이 작동하는 이유를 완전히 이해한다고 주장하지 않습니다. 따라서 누구든지이 답변을 편집하거나 설명하기 위해 의견을 남길 수 있다면 감사하겠습니다.
pepoluan현지화된 고정 장치를 사용하여 Django에서 manage.py migrate
를 실행할 때 이 오류가 발생했습니다.
우리 소스에는 # -*- coding: utf-8 -*-
선언이 포함되어 있으며 MySQL은 utf8에 대해 올바르게 구성되었으며 Ubuntu에는 /etc/default/locale
에 적절한 언어 팩과 값이 있습니다.
문제는 단순히 Django 컨테이너(도커 사용)에 LANG
env var가 누락되었다는 것입니다.
LANG
를 en_US.UTF-8
설정하고 마이그레이션을 다시 실행하기 전에 컨테이너를 다시 시작하면 문제가 해결되었습니다.
followben권장되는 솔루션은 저에게 효과가 없었고 ASCII가 아닌 모든 문자를 덤프하면서 살 수 있었습니다.
s = s.encode('ascii',errors='ignore')
오류를 일으키지 않는 벗겨진 무언가를 남겼습니다.
Gulzar답변이 늦었지만 이 오류는 특정 문자를 지원하지 않는 터미널 인코딩과 관련이 있습니다.
다음을 사용하여 python3
import sys import io sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8') print("é, à, ...")
Pedro Lobito여기의 많은 답변(예: @agf 및 @Andbdrew)은 이미 OP 질문의 가장 즉각적인 측면을 해결했습니다.
그러나 대부분 무시되어 온 미묘하지만 중요한 측면이 하나 있다고 생각합니다. 이는 Python에서 인코딩을 이해하려고 하는 동안 나와 같은 모든 사람에게 매우 중요합니다. Python 2 대 Python 3 문자 표현 관리는 크게 다릅니다. . 사람들이 버전을 인식하지 않고 Python의 인코딩에 대해 읽는 것과 관련하여 큰 혼란이 있다고 생각합니다.
OP 문제의 근본 원인을 이해하는 데 관심이 있는 사람은 Spolsky의 문자 표현 및 유니코드 소개를 읽은 다음 Python 2 및 Python 3에서 유니코드의 Batchelder로 이동하는 것이 좋습니다.
Simón Ramírez Amaya변수를 str(변수)로 변환하지 않도록 하십시오. 때로는 문제를 일으킬 수 있습니다.
피해야 할 간단한 팁:
try: data=str(data) except: data = data #Don't convert to String
위의 예는 인코딩 오류도 해결합니다.
sam ruben이 지원되지 않는 인코딩 문자열 ( data_that_causes_this_error
)을 일부 파일(예: results.txt
)에 쓰는 일반적인 경우에는 작동합니다.
f = open("results.txt", "w") f.write(data_that_causes_this_error.encode('utf-8')) f.close()
Pe Dro그것은 나를 위해 작동합니다 :
export LC_CTYPE="en_US.UTF-8"
Vanderpacket_data = "This is data"
와 같은 packet_data
초기화 직후 다음 줄에서 이 작업을 수행합니다.
unic = u'' packet_data = unic
Nandan KulkarniPython 3.0 이상에 대한 업데이트. Python 편집기에서 다음을 시도하십시오.
locale-gen en_US.UTF-8 export LANG=en_US.UTF-8 LANGUAGE=en_US.en LC_ALL=en_US.UTF-8
이것은 시스템의 기본 로케일 인코딩을 UTF-8 형식으로 설정합니다.
PEP 538 - 레거시 C 로케일을 UTF-8 기반 로케일로 강제 변환에서 더 많은 것을 읽을 수 있습니다.
ZF007stdout
으로 출력하려고 시도했지만 sys.stdout.write
를 사용하여 이 문제가 발생했습니다(다른 파일로도 출력을 지원할 수 있도록).
BeautifulSoup의 자체 문서 에서 코덱 라이브러리로 이 문제를 해결했습니다.
import sys import codecs def main(fIn, fOut): soup = BeautifulSoup(fIn) # Do processing, with data including non-ASCII characters fOut.write(unicode(soup)) if __name__ == '__main__': with (sys.stdin) as fIn: # Don't think we need codecs.getreader here with codecs.getwriter('utf-8')(sys.stdout) as fOut: main(fIn, fOut)
palswim이 문제는 django 프로젝트가 Apache를 사용하여 배포할 때 자주 발생합니다. Apache는 /etc/sysconfig/httpd에서 환경 변수 LANG=C를 설정하기 때문입니다. 파일을 열고 이 설정을 주석 처리(또는 취향에 맞게 변경)하기만 하면 됩니다. 또는 WSGIDaemonProcess 명령의 lang 옵션을 사용합니다. 이 경우 다른 LANG 환경 변수를 다른 가상 호스트로 설정할 수 있습니다.
shmakovpn출처 : http:www.stackoverflow.com/questions/9942594/unicodeencodeerror-ascii-codec-cant-encode-character-u-xa0-in-position-20