programing

UnicodeEncodeError: 'ascII' 코덱이 위치 20에서 문자 u'\xa0'을 인코딩할 수 없음: 서수가 범위(128)에 없음

prostudy 2022. 4. 9. 08:20
반응형

UnicodeEncodeError: 'ascII' 코덱이 위치 20에서 문자 u'\xa0'을 인코딩할 수 없음: 서수가 범위(128)에 없음

다른 웹 페이지(다른 사이트)에서 가져온 텍스트에서 유니코드 문자를 처리하는 데 문제가 있어.BeautifulSoup을 사용하고 있다.

문제는 오류가 항상 재현 가능한 것은 아니며, 때로는 일부 페이지와 함께 작동하기도 하고, 때로는 a를 던져 barfing하기도 한다는 것이다.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유니코드에서 인코딩된 텍스트/바이트로 변환한다.

대신 적절하게 사용하여 문자열을 인코딩하십시오.

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

또는 완전히 유니코드로 작동한다.

이건 전형적인 파이톤 유니코드 통증점이야!다음을 고려하십시오.

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로 바이트를 명시적으로 인코딩하고 python에게 사용할 코덱을 지정하십시오.

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil\u00E0!

문제는 str()를 호출할 때 python이 기본 문자 인코딩을 사용하여 제공된 바이트를 인코딩하려고 시도한다는 것이다. 이 바이트는 때때로 유니코드 문자의 표현이다.문제를 해결하려면 python에게 .encode('whatever_unicode')를 사용하여 자신이 준 스트링을 처리하는 방법을 알려야 한다.대부분의 경우 utf-8을 사용해도 괜찮을 것이다.

이 주제에 대한 훌륭한 설명을 보려면 Ned Batchelder의 PyCon 강연을 참조하십시오. http://nedbatchelder.com/text/unipain.html

나는 기호를 제거하고 끈을 끈처럼 계속 유지하는 우아한 작업을 주변에서 발견했다.

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

여기서 볼 수 있듯이, 무시 옵션을 사용하면 유니코드(및 국제화)를 사용하는 코드에서 지원하는 모든 유니코드(및 유니코드 변환)가 자동으로 삭제되기 때문에 위험하다는 점에 유의하십시오.

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'

글쎄, 나는 모든 것을 시도했지만 도움이 되지 않았다. 구글을 둘러본 후 나는 다음과 같은 것을 알아냈고 그것이 도움이 되었다.python 2.7이 사용되고 있다.

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')

인쇄마저 실패하게 하는 미묘한 문제는 환경변수를 잘못 설정하는 것이다. 예를 들어 LC_ALL은 "C"로 설정된다.데비안에서는 데비안 위키를 로케일로 설정하지 않는다.

$ 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à

문제는 유니코드 문자를 인쇄하려고 하는데 단말기가 지원하지 않는다는 겁니다.

은 할할수 수 installing을 해 볼 수 .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에서 문제 및 솔루션 시연

  1. VM 초기화 및 프로비저닝(예: 사용):

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
    

    See: available Ubuntu boxes..

  2. 유니코드 문자 인쇄(예: 트레이드 마크 기호:):

    $ 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)
    
  3. 지금 설치 중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.
    
  4. 이제 문제를 해결해야 한다.

    $ python -c 'print(u"\u2122");'
    ™
    
  5. 그렇지 않은 경우 다음 명령을 시도해 보십시오.

    $ LC_ALL=C.UTF-8 python -c 'print(u"\u2122");'
    ™
    

셸 내:

  1. 다음 명령을 사용하여 지원되는 UTF-8 로케일을 찾으십시오.

    locale -a | grep "UTF-8"
    
  2. 스크립트를 실행하기 전에 내보내기(예:

    export LC_ALL=$(locale -a | grep UTF-8)
    

    또는 다음과 같이 수동으로:

    export LC_ALL=C.UTF-8
    
  3. 예를 들어 특수 문자를 인쇄하여 테스트하십시오.:

    python -c 'print(u"\u2122");'
    

위는 우분투에서 시험했다.

나는 사실 대부분의 경우 그러한 캐릭터들을 제거하는 것이 훨씬 더 간단하다는 것을 발견했다.

s = mystring.decode('ascii', 'ignore')

나에게 효과가 있었던 것은 다음과 같았다.

BeautifulSoup(html_text,from_encoding="utf-8")

이게 누군가에게 도움이 되길 바래.

여기 소위 "cop out"이라고 불리는 몇몇 다른 대답들의 재탕이 있다.국내의 반대에도 불구하고, 골치 아픈 캐릭터/스트레인을 그냥 버리는 것이 좋은 해결책이 될 수 있는 상황이 있다.

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

UPDATE: 내 원래 대답은 Python 2를 위해 쓰여졌다.Python 3의 경우:

def safeStr(obj):
    try: return str(obj).encode('ascii', 'ignore').decode('ascii')
    except: return ""

참고: A을(를) 남기시려면?표를 로 지정한다.replace대신에ignore오류 처리기에 대한 인코딩 호출 중.

제안: 이 기능의 이름을 지정하십시오.toAscii대에? 선호의 그건 선호의 문제야...

마지막으로, 다음과 같은 보다 강력한 PY2/3 버전이 있다.six, 사용하기로 선택한 위치replace그리고 화려한 유니코드 인용문 및 아포스트로피를 아스키 세트의 일부인 단순한 수직으로 대체하기 위해 일부 문자 스왑을 했다.이러한 스왑을 직접 확장하십시오.

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' ) )

스크립트 시작 부분에 아래 줄 추가(또는 두 번째 줄):

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

그것은 파이톤 소스 코드 인코딩의 정의 입니다.자세한 내용은 PEP 263을 참조하십시오.

나는 항상 아래 코드를 파이톤 파일의 처음 두 줄에 넣는다.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

아아, 이건 파이톤 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'))

여기서 오류는 인코딩에서 무시된다.

여기에서 간단한 도우미 기능.

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')

변수 인코드에 추가('utf-8')

agent_contact.encode('utf-8')

나한테는 효과가 있어:

export LC_CTYPE="en_US.UTF-8"

터미널을 열고 다음 명령을 실행하십시오.

export LC_ALL="en_US.UTF-8"

나는 단지 다음을 사용했다.

import unicodedata
message = unicodedata.normalize("NFKD", message)

이에 대한 설명서의 내용을 확인하십시오.

유니코다타.normalize(양식, 불신) 유니코드 문자열에 대한 일반 양식 양식을 잘못 반환하십시오.유효한 형식 값은 'NFC', 'NFKC', 'NFD', 'NFKD'이다.

유니코드 표준은 표준 등가성 및 호환성 등가성의 정의에 기초하여 유니코드 문자열의 다양한 표준화 형식을 정의한다.유니코드에서는 여러 문자를 다양하게 표현할 수 있다.예를 들어, U+00C7 문자(LATIN CAPTAR LEAD C WITH CEDILA)는 U+0043(LATIN CAPTAR LEATter C) U+0327(COMING CEDILA) 시퀀스로도 표현할 수 있다.

각 문자에 대해, 정상 형태 C와 정상 형태 D의 두 가지 형태가 있다.NFD(Normal Form D)는 표준 분해라고도 하며, 각 문자를 분해된 형태로 변환한다.정상형 C(NFC)는 먼저 표준 분해법을 적용한 다음, 사전 결합 문자를 다시 컴파일한다.

이 두 가지 형태 외에도 호환성 등가성에 기반한 두 가지 정규 양식이 추가로 있다.유니코드에서는 일반적으로 다른 문자와 통일되는 특정 문자가 지원된다.예를 들어 U+21160(로마누메랄 원)은 정말로 U+0049(라틴 대문자 I)와 같은 것이다.단, 기존 문자 집합과의 호환성을 위해 유니코드에서 지원한다(예: gb2312).

정규 형식 KD(NFKD)는 호환성 분해(즉, 모든 호환성 문자를 동등한 것으로 교체)를 적용한다.정상형 KC(Normal Form KC, NFKC)는 먼저 호환성 분해를 적용하고, 그 다음에 표준형 구성을 적용한다.

두 유니코드 문자열이 정상화되고 인간 독자와 똑같이 보이더라도 한 사람이 결합한 문자를 가지고 있고 다른 한 사람은 그렇지 않으면 동등하게 비교되지 않을 수 있다.

날 위해 해결해주지간단하고 쉽다.

아래 솔루션이 내게 효과가 있었습니다, 방금 추가

u "스트링"

내 문자열 앞에 있는 문자열을 유니코드로 표시하십시오.

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)

답장이 늦었지만, 이 오류는 특정 문자를 지원하지 않는 터미널의 인코딩과 관련이 있다.
나는 그것을 에 고정시켰다.python3사용:

import sys
import io

sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
print("é, à, ...")

방금 이 문제가 있었는데 구글이 나를 여기로 안내해줬어. 그래서 여기 일반적인 해결책들을 덧붙이자면, 이것이 내게 효과가 있었던 거야.

# 'value' contains the problematic data
unic = u''
unic += value
value = unic

나는 네드의 발표를 읽고 이런 생각을 했다.

하지만 나는 이것이 왜 효과가 있는지 완전히 이해해야 한다고 주장하지는 않는다.그래서 이 답을 수정하거나 설명을 위해 댓글을 달 수 있는 사람이 있다면 고맙겠다.

실행 중에 이 오류가 발생함manage.py migrate현지화된 설비를 갖춘 장고에서

우리 정보원에는 다음이 포함되어 있었다.# -*- coding: utf-8 -*-선언, MySQL이 utf8에 맞게 올바르게 구성되었고 Ubuntu는 다음 위치에 적절한 언어 팩과 값을 가지고 있었다./etc/default/locale.

쟁점은 단순히 장고 컨테이너(우린 도커를 사용한다)가 빠진 것이었다.LANG동경의 대상

LANGen_US.UTF-8그리고 마이그레이션을 다시 실행하기 전에 컨테이너를 재시작하여 문제를 해결했다.

python 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 기반 로케일로 강제 설정에서 확인할 수 있다.

권장 해결책은 내게는 통하지 않았고, 아스키가 아닌 모든 문자를 덤핑하면서 살아갈 수 있었기 때문에.

s = s.encode('ascii',errors='ignore')

실수를 하지 않는 뭔가가 벗겨졌지

일반적으로 이 지원되지 않는 인코딩 문자열을 쓰는 경우(예:data_that_causes_this_error(예를 들어, 일부 파일에 대해) results.txt)), 이것은 효과가 있다.

f = open("results.txt", "w")
  f.write(data_that_causes_this_error.encode('utf-8'))
  f.close()

인쇄 전표에 문제가 있는 경우, 많은 시간이 걸려서 단자 인쇄에 문제가 생길 수 있다.이것은 나에게 도움이 되었다:export PYTHONIOENCODING=UTF-8

여기서의 많은 대답(예: @agf와 @Andbdrew)은 이미 OP 질문의 가장 직접적인 측면을 다루었다.

그러나, 나는 대체로 무시되어 왔고 나를 좋아하는 모든 사람들에게 매우 중요한 한 가지 미묘하지만 중요한 측면이 있다고 생각한다. 그것은 결국 파이썬에서 인코딩을 이해하려고 노력하다가 여기에 이르게 되었다.Python 2와 Python 3의 캐릭터 표현 관리는 크게 다르다.나는 사람들이 버전도 모른 채 파이썬의 암호화에 대해 읽는 것과 큰 혼란의 덩어리가 연관되어 있다고 생각한다.

나는 OP 문제의 근본 원인을 이해하는 데 관심이 있는 사람이라면 캐릭터 표현과 유니코드에 대한 스폴스키의 소개를 읽고 나서 파이썬 2와 파이썬 3의 유니코드에 있는 배첼더로 옮겨가는 것으로 시작할 것을 제안한다.

변수가 str(변수)로 변환되지 않도록 하십시오.때때로, 그것은 문제를 일으킬 수도 있다.

피할 수 있는 간단한 팁:

try: 
    data=str(data)
except:
    data = data #Don't convert to String

위의 예시로는 인코드 에러도 해결할 것이다.

이런 게 있으면.packet_data = "This is data"다음 라인에서 초기화 후 바로 실행packet_data:

unic = u''
packet_data = unic

유니코드 문자를 출력하는 동안 이 문제가 발생함stdout, 그러나.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)

참조URL: https://stackoverflow.com/questions/9942594/unicodeencodeerror-ascii-codec-cant-encode-character-u-xa0-in-position-20

반응형