UnicodeDecodeError : 'ascii'코덱은 위치 2에서 0xd1 바이트를 디코딩 할 수 없습니다. 서 수가 범위에 없습니다 (128).


107

비표준 문자가 포함 된 매우 큰 데이터 세트로 작업하려고합니다. 작업 사양에 따라 유니 코드를 사용해야하지만 당황합니다. (그리고 아마도 모든 것을 잘못하고 있습니다.)

다음을 사용하여 CSV를 엽니 다.

 15     ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"')

그런 다음 다음으로 인코딩을 시도합니다.

name=school_name.encode('utf-8'), street=row[9].encode('utf-8'), city=row[10].encode('utf-8'), state=row[11].encode('utf-8'), zip5=row[12], zip4=row[13],county=row[25].encode('utf-8'), lat=row[22], lng=row[23])

API로 보내야하기 때문에 lat 및 lng를 제외한 모든 것을 인코딩하고 있습니다. 프로그램을 실행하여 데이터 세트를 내가 사용할 수있는 것으로 구문 분석하면 다음과 같은 Traceback이 표시됩니다.

Traceback (most recent call last):
  File "push_into_db.py", line 80, in <module>
    main()
  File "push_into_db.py", line 74, in main
    district_map = buildDistrictSchoolMap()
  File "push_into_db.py", line 32, in buildDistrictSchoolMap
    county=row[25].encode('utf-8'), lat=row[22], lng=row[23])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

python 2.7.2를 사용하고 있으며 이것은 django 1.4에서 앱 빌드의 일부라고 말해야한다고 생각합니다. 이 주제에 대한 여러 게시물을 읽었지만 직접 적용되는 게시물은 없습니다. 어떤 도움이라도 대단히 감사하겠습니다.

문제를 일으키는 일부 비표준 문자가 Ñ이고 가능하면 É인지 알고 싶을 수도 있습니다.


1
원본 파일 인코딩은 무엇입니까? 원래 인코딩에 따라 디코딩 한 다음 utf 8로 변환해야한다고 생각합니다
xiao 啸

답변:


152

유니 코드는 UTF-8과 같지 않습니다. 후자는 전자의 인코딩 일뿐 입니다.

당신은 그것을 잘못된 방식으로하고 있습니다. 당신은된다 읽는 UTF-8 인코딩 이 필요하므로, 데이터를 디코딩 유니 코드 문자열로 UTF-8 인코딩 된 문자열.

그러니 그냥 교체 .encode와 함께 .decode, 그것이 작동해야합니다 (.CSV 인 경우 UTF-8 인코딩).

하지만 부끄러워 할 것은 없습니다. 프로그래머 5 명 중 3 명은 처음에는 이것을 이해하는 데 어려움을 겪었습니다.

업데이트 : 입력 데이터가 UTF-8로 인코딩 되지 않은.decode() 경우에는 물론 적절한 인코딩 을 사용해야합니다 . 아무것도 주어지지 않으면 python은 ASCII가 아닌 문자에서 분명히 실패하는 ASCII를 가정합니다.


1
오류의 원인은 Python이 기본 인코딩 인 ASCII에서이를 자동으로 디코딩하여 지정한대로 UTF-8로 인코딩 할 수 있기 때문입니다. 데이터가 유효한 ASCII가 아니기 때문에 작동하지 않습니다.
agf

7
물론, UTF8로 인코딩 된 데이터 라면 (내가 추측 했듯이 ) .decode('utf-8')트릭 을 해야할까요?
ch3ka

물론, 당신 말이 맞을 것입니다. 이 상황에서 특정 오류가 발생하는 이유를 설명했습니다.
agf

1
완전한! 대단히 감사합니다. 그래서 그것이 .decode ( 'latin-1') 이었다는 것이 밝혀졌습니다. 이것은 나에게 문제를주고 있었기 때문에 이치에 맞습니다. 다시! 감사합니다!
jelkimantis

귀하의 솔루션은 경우에 따라 작동하지만 이것을 사용하면 다른 오류 'ascii'코덱이 위치 2에 문자 u '\ xf1'을 인코딩 할 수 없습니다 (128)
Vikash Mishra

84

다음 줄을 코드에 추가하십시오.

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

5
`AttributeError : 'sys'모듈에 'setdefaultencoding'속성이 없습니다. Python 3에서 작동하지 않는 것 같습니다
skjerns

우 우우우! 이것은 나를 도왔다.
Shougo Makishima

1
내 Python 2.7에서 작동하며 reload (sys)가 필요합니다. 그렇지 않으면 setdefaultencoding에 액세스 할 수 없습니다.
Yu Shen

1
그것은 많은 질문에서 나를 위해 작동하게 만든 유일한 것입니다. 정말 고마워!
Freedo

이름 'reload'가 정의되지 않았습니다
Davide

28

Python 3 사용자 용. 넌 할 수있어

with open(csv_name_here, 'r', encoding="utf-8") as f:
    #some codes

그것은 플라스크에서도 작동합니다 :)


1
내가 여기를 통해 누군가를 도운 것은 처음입니다. :) 좋은 내가 도움이 아는 느낌
Skrmnghrd

1
그리고 당신은 나에게도 도왔습니다 :) 다른 모든 답변은 파일 읽기에 효과가 없었습니다. 이제 글쓰기를 위해서도 수정하는 방법을 찾아야합니다;)
user2194898

코드 링크를 보내주실 수 있습니까? 나는 도움을하려고합니다
Skrmnghrd

9

오류의 주된 이유는 python이 가정하는 기본 인코딩이 ASCII이기 때문입니다. 따라서 인코딩 할 문자열 데이터 encode('utf8')에 ASCII 범위 밖에있는 문자 (예 : 'hgvcj 터 파크 387'과 같은 문자열)가 포함 된 경우 문자열이 예상되는 인코딩 형식이 아니기 때문에 Python에서 오류가 발생합니다.

버전 3.5 이전의 python 버전을 사용하는 경우 안정적인 수정은 python이 가정하는 기본 인코딩을 다음과 같이 설정하는 것입니다 utf8.

import sys
reload(sys)
sys.setdefaultencoding('utf8')
name = school_name.encode('utf8')

이런 식으로 파이썬은 ASCII 범위를 벗어나는 문자열 내의 문자를 예상 할 수 있습니다.

단, 파이썬 버전 3.5 이상을 사용하는 경우 reload () 함수를 사용할 수 없으므로 디코드를 사용하여 수정해야합니다.

name = school_name.decode('utf8').encode('utf8')

당신의 대답과 광산의 차이 무엇인가
khelili miliana

1
좀 더 자세하게. 사람들은 종종 인과 적 세부 사항이 도움이된다고 생각합니다. 그리고 귀하의 코드는 btw로 작동하며 훼손되지 않습니다.
Temi Fakunle

1
reload는 Python 3에서 사용할 수 있습니다. 가져 오기만하면됩니다. imp import reload
Meow

@Meow 그러나 Python 3에는 sys.setdefaultencoding이 없습니다. 따라서 호환성 py2 \ py3의 맥락에서 일부 검사가 수행됩니다. sys.getdefaultencoding () 아마도. 그 문제에 대한 조언을 주시면 감사하겠습니다. stackoverflow.com/questions/28127513/…
Konst54

2

Python 3 사용자의 경우 :

인코딩을 'ascii'에서 'latin1'로 변경하면 작동합니다.

또한 아래 스 니펫을 사용하여 상위 10000 바이트를 읽어 인코딩을 자동으로 찾을 수 있습니다.

import chardet  
with open("dataset_path", 'rb') as rawdata:  
            result = chardet.detect(rawdata.read(10000))  
print(result)

2

내 컴퓨터에 잘못된 로케일이 설정되어 있습니다.

내가 먼저 했어

>>> import locale
>>> locale.getpreferredencoding(False)
'ANSI_X3.4-1968'

locale.getpreferredencoding(False)open()인코딩을 제공하지 않을 때 호출되는 함수 입니다. 출력은이어야 'UTF-8'하지만이 경우에는 ASCII 변형입니다 .

그런 다음 bash 명령을 실행 locale하고이 출력을 얻었습니다.

$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

그래서 파이썬이 UTF-8 대신 ASCII로 파일을 열도록하는 기본 Ubuntu 로케일을 사용하고있었습니다. 로케일 을 다음 으로 설정 해야했습니다.en_US.UTF-8

sudo apt install locales 
sudo locale-gen en_US en_US.UTF-8    
sudo dpkg-reconfigure locales

로케일 시스템 전체를 변경할 수없는 경우 다음과 같이 모든 Python 코드를 호출 할 수 있습니다.

PYTHONIOENCODING="UTF-8" python3 ./path/to/your/script.py

또는

export PYTHONIOENCODING="UTF-8"

실행하는 셸에서 설정합니다.


1

인증서를 생성하거나 갱신하는 동안 certbot을 실행하는 동안이 문제가 발생하면 다음 방법을 사용하십시오.

grep -r -P '[^\x00-\x7f]' /etc/apache2 /etc/letsencrypt /etc/nginx

이 명령은 주석의 한 .conf 파일에서 문제가되는 문자 "´"를 찾았습니다. 그것을 제거하고 (원하는대로 주석을 편집 할 수 있음) nginx를 다시로드하면 모든 것이 다시 작동했습니다.

출처 : https://github.com/certbot/certbot/issues/5236


0

또는 유니 코드 텍스트 인 경우 Python에서 텍스트를 다룰 때 유니 코드라는 점에 유의하십시오.

text=u'unicode text'대신 설정하십시오 text='unicode text'.

이것은 내 경우에 효과가 있습니다.


0

위도와 경도 때문에 UTF 16 인코딩으로 열립니다.

with open(csv_name_here, 'r', encoding="utf-16") as f:

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