UnicodeDecodeError: 'ascii' codec bileşeni, 2 konumundaki bayt 0xd1'in kodunu çözemiyor: ordinal aralıkta değil (128)


107

İçinde bazı standart olmayan karakterler bulunan çok büyük bir veri kümesiyle çalışmaya çalışıyorum. İş özelliklerine göre unicode kullanmam gerekiyor, ancak şaşkınım. (Ve muhtemelen her şeyi yanlış yapmak.)

CSV'yi şunu kullanarak açıyorum:

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

Sonra onu şu şekilde kodlamaya çalışıyorum:

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

Enlem ve lng hariç her şeyi kodluyorum çünkü bunların bir API'ye gönderilmesi gerekiyor. Veri kümesini kullanabileceğim şeylere ayrıştırmak için programı çalıştırdığımda, aşağıdaki Traceback'i alıyorum.

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)

Sanırım size python 2.7.2 kullandığımı söylemeliyim ve bu, django 1.4'te yapılan bir uygulamanın bir parçası. Bu konuyla ilgili birkaç yazı okudum, ancak hiçbiri doğrudan geçerli görünmüyor. Herhangi bir yardım çok takdir edilecektir.

Soruna neden olan bazı standart olmayan karakterlerin Ñ ve muhtemelen É olduğunu da bilmek isteyebilirsiniz.


1
Orijinal dosya kodlamanız nedir? Bence bunu orijinal kodlamaya göre
çözmeniz

Kodlamanın olası kopyası "'ascii' codec'i karakter kodlayamaz… ordinal aralıkta değil (128)" verir [Ed .: ve yaklaşık bir zilyon diğerinin de, eminim.]
Karl Knechtel

Yanıtlar:


152

Unicode, UTF-8'e eşit değildir. İkincisi, sadece birincisi için bir kodlamadır .

Yanlış yapıyorsun. Sen edilir okuma UTF-8- kodlanmış Eğer zorunda, verileri deşifre unicode dizesine UTF-8 kodlu Dize.

Bu nedenle , .encodeile değiştirin .decodeve çalışmalıdır (.csv dosyanız UTF-8 kodluysa).

Yine de utanılacak bir şey yok. Bahse girerim 5 programcının 3'ü ilk başta bunu anlamakta güçlük çekti, hatta daha fazlası değil;

Güncelleme: Giriş verileriniz UTF-8 kodlu değilse , o zaman .decode()elbette uygun kodlamayı yapmanız gerekir . Hiçbir şey verilmemişse python, ASCII olmayan karakterlerde açıkça başarısız olan ASCII'yi varsayar.


1
Hatanın nedeni, Python'un varsayılan kodlamadan (ASCII) otomatik olarak kodunu çözmeye çalışmasıdır, böylece daha sonra belirtildiği gibi UTF-8'e kodlayabilir. Veriler geçerli ASCII olmadığından çalışmaz.
agf

7
elbette, ancak UTF8 kodlu veri ise (tahmin ettiğim gibi), o zaman .decode('utf-8')hile yapmalı mı?
ch3ka

Tabii, muhtemelen haklısın. Ben sadece bu durumda neden bu belirli hatayı aldığını açıklıyordum.
agf

1
Mükemmel! Çok teşekkür ederim. Öyleyse bunun .decode ('latin-1') olduğu ortaya çıktı - bu mantıklı çünkü bana problemi veren was idi. Tekrar! Teşekkür ederim!
jelkimantis

Çözümünüz bazı durumlarda işe yarıyor, ancak bunu kullanırsam başka bir hata 'ascii' codec'i konum 2'de u '\ xf1' karakterini kodlayamıyor: ordinal aralıkta değil (128)
Vikash Mishra

84

Bu satırları kodlarınıza eklemeniz yeterlidir:

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

5
"AttributeError: 'sys' modülünün 'setdefaultencoding' özniteliği yok Python 3'te çalışmıyor
skjerns

Woot woot! Bu bana yardımcı oldu.
Shougo Makishima

1
Python 2.7 için çalışıyor, not, yeniden yükleme (sys) gerekiyor, aksi takdirde setdefaultencoding erişilemez.
Yu Shen

1
Pek çok SO sorusu arasında benim için çalışmasını sağlayan tek şey buydu. Çok teşekkürler!
Freedo

'yeniden yükleme' adı tanımlanmadı
Davide

28

Python 3 kullanıcıları için. yapabilirsin

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

şişesi ile de çalışır :)


1
Buraya ilk kez yardım ettim. Yardım ettiğimi bilmek iyi hissettiriyor :)
Skrmnghrd

1
Bana da yardımcı oldunuz :) Diğer tüm cevaplar dosya okumak için işe yaramadı. Şimdi bunu yazmak için de nasıl düzelteceğimi bulmam gerekiyor;)
user2194898

bana kodunun bağlantısını gönderebilir misin? Yardım etmeye çalışacağım
Skrmnghrd

9

Hatanın ana nedeni, python tarafından varsayılan kodlamanın ASCII olmasıdır. Dolayısıyla, kodlanacak dize verileriencode('utf8') ASCII aralığının dışında bir karakter içeriyorsa, örneğin 'hgvcj 터 파크 387' gibi bir dizge için, python hata verir çünkü dizge beklenen kodlama biçiminde değildir.

3.5 sürümünden önceki bir python sürümünü kullanıyorsanız, güvenilir bir düzeltme, python tarafından varsayılan kodlamayı şu şekilde ayarlamak olacaktır utf8:

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

Bu şekilde python, ASCII aralığının dışında kalan bir dizedeki karakterleri tahmin edebilir.

Bununla birlikte, python sürüm 3.5 veya üstünü kullanıyorsanız, reload () işlevi kullanılamaz, bu nedenle kod çözme kullanarak düzeltmeniz gerekir.

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

senin
cevabınla

1
Daha detaylı. İnsanlar genellikle nedensel ayrıntıları yararlı bulur. Ve kodunuz btw çalışıyor, hiçbir derogasyon amaçlanmadı.
Temi Fakunle

1
yeniden yükleme Python 3'te mevcuttur, sadece içe aktarmanız gerekir. imp ithalat yeniden yüklemesinden
Meow

@Meow ama Python 3'te sys.setdefaultencoding yok. Yani py2 \ py3 uyumluluğu bağlamında bazı kontroller yapacak, sys.getdefaultencoding () belki. Bu konuyla ilgili bir tavsiye için minnettar olurum. stackoverflow.com/questions/28127513/…
Konst54

2

Python 3 kullanıcıları için:

kodlamanın 'ascii'den' latin1'e değiştirilmesi işe yarar.

Ayrıca, aşağıdaki kod parçacığını kullanarak en iyi 10000 baytı okuyarak kodlamayı otomatik olarak bulmayı deneyebilirsiniz:

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

2

Bilgisayarım yanlış yerel ayarlara sahip.

İlk ben yaptım

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

locale.getpreferredencoding(False)open()bir kodlama sağlamadığınız zaman tarafından çağrılan işlevdir . Çıktı olmalıdır 'UTF-8', ancak bu durumda ASCII'nin bir çeşididir .

Sonra bash komutunu çalıştırdım localeve bu çıktıyı aldım

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

Bu yüzden, Python'un dosyaları UTF-8 yerine ASCII olarak açmasına neden olan varsayılan Ubuntu yerel ayarını kullanıyordum. Ben zorunda benim yerel ayarı içinen_US.UTF-8

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

Yerel sistemi tamamen değiştiremezseniz, tüm Python kodunuzu şu şekilde çalıştırabilirsiniz:

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

veya yap

export PYTHONIOENCODING="UTF-8"

onu çalıştırdığınız kabukta ayarlamak için.


1

Sertifika oluştururken veya yenilerken certbot'u çalıştırırken bu sorunu yaşarsanız, lütfen aşağıdaki yöntemi kullanın

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

Bu komut, yorumdaki bir .conf dosyasında sorun teşkil eden "´" karakterini buldu. Kaldırdıktan sonra (yorumları istediğiniz gibi düzenleyebilirsiniz) ve nginx'i yeniden yükledikten sonra her şey yeniden çalıştı.

Kaynak: https://github.com/certbot/certbot/issues/5236


0

Ya da Python'da bir Unicode metin ise metinle uğraşırken Unicode olduğunu not edin.

text=u'unicode text'Bunun yerine sadece ayarlayın text='unicode text'.

Bu benim durumumda çalıştı.


0

lat ve long nedeniyle UTF 16 kodlamasıyla açın.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.