UnicodeDecodeError: 'utf8' codec bileşeni bayt 0x9c kodunu çözemiyor


289

İstemcilerden UTF-8 geçerli karakterleri almak gerekiyordu bir soket sunucusu var.

Sorun şu ki, bazı istemciler (özellikle bilgisayar korsanları) tüm yanlış türde verileri gönderiyor.

Orijinal istemciyi kolayca ayırt edebilirim, ancak daha sonra analiz edebilmek için gönderilen tüm verileri dosyalara kaydediyorum.

Bazen hataya œneden olan böyle karakterler UnicodeDecodeErroralıyorum.

Bu karakterler ile veya bu karakter olmadan dize UTF-8 yapabilmek gerekir.


Güncelleme:

Benim özel durum için soket hizmeti bir MTA oldu ve bu nedenle sadece gibi ASCII komutları almak için bekliyoruz:

EHLO example.com
MAIL FROM: <john.doe@example.com>
...

Tüm bunları JSON'da kaydediyordum.

Sonra iyi niyetli olmayan bazı insanlar her türlü çöpü satmaya karar verdiler.

Bu yüzden özel durumum için ASCII olmayan karakterleri soymak mükemmel bir şekilde tamam.


1
dize bir dosyadan mı yoksa yuvadan mı çıkıyor? soketin / dosya işleyicisinden gönderilmeden önce dizenin nasıl kodlandığına ve kod çözülmesine ilişkin kod örneklerini gönderebilir misiniz?
devsnd

Yazdım mı yoksa dizenin soketten geldiğini yazmadım mı? Ben sadece soketten dize okumak ve ile bir sözlük koymak ve sonra birlikte göndermek için JSON. JSON işlevi bu karakterler nedeniyle başarısız oldu.
transilvlad

örnek verilerinizi koyabilir misiniz
Shubham Sharma

Yanıtlar:


343

http://docs.python.org/howto/unicode.html#the-unicode-type

str = unicode(str, errors='replace')

veya

str = unicode(str, errors='ignore')

Not: Bu, dizeyi onlar olmadan döndüren söz konusu karakterleri çıkarır (yok sayar).

Benim için ideal bir durum çünkü benim uygulama tarafından izin verilmeyen ASCII olmayan girişe karşı koruma olarak kullanıyorum.

Alternatif olarak:codecs Dosyada okumak için modülün open yöntemini kullanın :

import codecs
with codecs.open(file_name, 'r', encoding='utf-8',
                 errors='ignore') as fdata:

45
Evet, ancak bu genellikle kötü bir uygulamadır / tehlikelidir, çünkü sadece karakterleri kaybedersiniz. Giriş dizesinin kodlamasını belirlemek veya tespit etmek ve önce unicode olarak kodunu çözmek, sonra UTF-8 olarak kodlamak daha iyidir, örneğin:str.decode('cp1252').encode('utf-8')
Ben Hoyt

Bazı durumlarda evet haklısınız sorunlara neden olabilir. Benim durumumda, soket sunucuma bağlanan istemcilerin kötü biçimlendirmesi ve programlamasından kaynaklanan ek karakterler olduğu için onları umursamıyorum.
transilvlad

Bu aslında dize içeriği benim durumumda, aslında geçersizse yardımcı '\xc0msterdam'turnike u'\ufffdmsterdam'ile değiştirin
PvdL

3
bir dosyayı okumada sorun yaşadığınız için buraya geldiyseniz, dosyayı ikili modda açmak yardımcı olabilir: open(file_name, "rb")ve sonra yukarıdaki yorumlardan Ben'in yaklaşımını uygulayın
kristian

aynı seçenek daha da fazlası için geçerlidir, örneğin "something.decode ()"
Alexander Stohr

84

Motoru C'den Python'a değiştirmek benim için hile yaptı.

Motor C:

pd.read_csv(gdp_path, sep='\t', engine='c')

'utf-8' kodeki 18 konumunda bayt 0x92 kodunu çözemiyor: geçersiz başlangıç ​​baytı

Motor Python:

pd.read_csv(gdp_path, sep='\t', engine='python')

Benim için hata yok.


3
bu aslında iyi bir çözüm. neden indirildi bilmiyorum.
ℕʘʘḆḽḘ

1
Mükemmel cevap. Teşekkür ederim. Bu benim için çalıştı. Soruna neden olan bir elmas şekli karakterinin içinde "?" Düz gözlerle inç olan "" "vardı. Anlamak için 2 şey yaptım. a) df = pd.read_csv ('test.csv', n_rows = 10000). Bu motor olmadan mükemmel çalıştı. Bu yüzden hangi satırda hata olduğunu anlamak için n_rows arttı. b) df = pd.read_csv ('test.csv', motor = 'python'). Bu çalıştı ve ben df.iloc [36145] kullanarak hatalı satır yazdırdı, bu bana hatalı kayıt yazdırdı.
Jagannath Banerjee

2
Bu benim için de çalıştı ... 'başlık altında' ne olduğundan emin değilim ve bu aslında her durumda güzel / iyi / uygun bir
çözümse

1
Benim için çalıştı rağmen, ben bulmak o kadar kolay değil .. Nasıl dünyada dışarı birisi noktası dışarı ile onu anlamaya ki? Nereden geldiğini merak ediyorum ...
Green

1
Harika bir çözüm! Çok teşekkür ederim.
Pechi

62

Python 3'e taşındığım için bu tür bir sorun benim için kesiliyor.

Yukarıdakilerin hiçbiri benim için işe yaramadığında farklılıkların ve nasıl bir çözüm bulunacağının bu güzel açıklamasını buldum.

http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html

Kısacası, Python 3'ün Python 2 ile mümkün olduğunca benzer davranmasını sağlamak için:

with open(filename, encoding="latin-1") as datafile:
    # work on datafile here

Ancak, makaleyi okuyun, tüm çözüme uyan tek bir boyut yoktur.


29
>>> '\x9c'.decode('cp1252')
u'\u0153'
>>> print '\x9c'.decode('cp1252')
œ

16
Kafam karıştı, cp1252'yi nasıl seçtiniz? Benim için çalıştı, ama neden? Bilmiyorum ve şimdi kayboldum:. Açıklayabilir misiniz? Çok teşekkürler ! :)
Cyril N.

4
Tüm karakterler için uygun bir seçenek sunabilir misiniz? Daha genel bir kodun uygulanabilmesi için kodu çözülmesi gereken karakterleri tespit etmenin bir yolu var mı? Pek çok insanın buna baktığını görüyorum ve bazılarının atılmasının, benim için olduğu gibi istenen seçenek olmadığını iddia ediyorum.
transilvlad

Gördüğünüz gibi bu soru oldukça popüler. Cevabınızı daha genel bir çözümle genişletebileceğinizi mi düşünüyorsunuz?
transilvlad

13
"Tahmin kodlama rulet" için genel bir çözüm yok
Puppy

5
web arama, şans ve sezgi bir arada kullanarak bulundu: cp1252 wasused by default in the legacy components of Microsoft Windows in English and some other Western languages
bolov

24

Ben de aynı sorunu vardı UnicodeDecodeErrorve bu çizgi ile çözdü. En iyi yol olup olmadığını bilmiyorum ama benim için çalıştı.

str = str.decode('unicode_escape').encode('utf-8')

13

ilk olarak, kodlama dosya türünü almak için get_encoding_type kullanma:

import os    
from chardet import detect

# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']

ikincisi, aşağıdaki türdeki dosyaları açma:

open(current_file, 'r', encoding = get_encoding_type, errors='ignore')

1
geri döndüğünde ne olur Yok
Chop Labalagun

3

Birisinin aynı sorunu olması durumunda. YouCompleteMe ile vim kullanıyorum , bu hata mesajı ile ycmd başlatılamadı, yaptığım şey:, export LC_CTYPE="en_US.UTF-8"sorun gitti.


2
Bunun bu soru ile ilişkisi nedir?
transilvlad

1
Tamamen aynı, nasıl tamamladığınızı biliyorsanız. YCM eklentisi is soket mimarisi, istemci ve sunucu arasındaki iletişim soket kullanıyor, hem kodlama ayarı doğru değilse paketleri çözmesi mümkün piton modülleri değildir
workplaylifecycle

Aynı problemim var. Bana nereye koyacağımı söyleyebilir misin export LC_CTYPE="en_US.UTF-8"?
Reman

@Remonn merhaba, bash için profil dosyanız olduğunu biliyor musunuz? İçeri koy.
workplaylifecycle

@hylepo, ben bir windows sistemindeyim :)
Reman

3

Bir dosyada değişiklik yapmanız gerekiyor, ancak dosyanın kodlamasını bilmiyorsanız ne yapabilirsiniz? Kodlamanın ASCII uyumlu olduğunu ve yalnızca ASCII parçalarını incelemek veya değiştirmek istiyorsanız, dosyayı yedek dosya hata işleyicisiyle açabilirsiniz:

with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
    data = f.read()

0

Bu sorunu sadece ekleyerek çözdüm

df = pd.read_csv(fileName,encoding='latin1')
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.