UnicodeDecodeError: kodek „utf8” nie może zdekodować bajtu 0xa5 na pozycji 0: nieprawidłowy bajt początkowy

188

Używam Python-2.6 CGIskryptów, ale znalazłem ten błąd w dzienniku serwera podczas robienia json.dumps(),

Traceback (most recent call last):
  File "/etc/mongodb/server/cgi-bin/getstats.py", line 135, in <module>
    print json.dumps(​​__getdata())
  File "/usr/lib/python2.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa5 in position 0: invalid start byte

Tutaj,

​__get​data()funkcja zwraca dictionary {}.

Przed wysłaniem tego pytania skierowałem to pytanie jako SO.


AKTUALIZACJE

Poniższy wiersz szkodzi koderowi JSON,

now = datetime.datetime.now()
now = datetime.datetime.strftime(now, '%Y-%m-%dT%H:%M:%S.%fZ')
print json.dumps({'current_time': now}) // this is the culprit

Mam tymczasową poprawkę

print json.dumps( {'old_time': now.encode('ISO-8859-1').strip() })

Ale nie jestem pewien, czy to właściwy sposób.

Deepak Ingole
źródło
1
Wygląda na to, że w słowniku znajdują się dane tekstowe, których nie można zakodować / zdekodować. Co jest w środku dict?
mgilson
@mgilson yup master Zrozumiałem problem, ale nie wiem, jak sobie z tym poradzić .. dictmalist, dict, python timestamp value
Deepak Ingole
1
@Pilot - Niezupełnie. Prawdziwy problem tkwi gdzieś w środku __getdata. Nie wiem, dlaczego otrzymujesz znak, którego nie można odszyfrować. Możesz spróbować wymyślić łatki na dykt, aby działały, ale najczęściej są to po prostu prośby o więcej problemów później. Spróbowałbym wydrukować dyktando, aby zobaczyć, gdzie jest znak spoza ASCII. Następnie dowiedz się, w jaki sposób to pole zostało obliczone / ustawione i stamtąd pracuj wstecz.
mgilson
1
Miałem ten sam błąd podczas próby odczytania pliku .csv, który zawierał kilka znaków spoza ASCII. Usunięcie tych znaków (zgodnie z sugestią poniżej) rozwiązało problem.
Dmitriy R. Starson

Odpowiedzi:

87

Błąd jest spowodowany tym, że w słowniku znajduje się jakiś znak inny niż ASCII i nie można go zakodować / zdekodować. Prostym sposobem uniknięcia tego błędu jest zakodowanie takich ciągów za pomocą encode()funkcji w następujący sposób (jeśli ajest to ciąg ze znakiem innym niż ASCII):

a.encode('utf-8').strip()
Santosh Ghimire
źródło
2
Ponieważ UTF-8 jest wstecznie kompatybilny z oldschoolowym 7-bitowym ASCII, powinieneś po prostu zakodować wszystko. Dla znaków z 7-bitowego zakresu ASCII to kodowanie będzie odwzorowaniem tożsamości.
Tadeusz A. Kadłubowski
29
To nie wydaje się jasne. Podczas importowania pliku CSV, jak używasz tego kodu?
Dave
Ten sam problem pojawia się podczas wykonywania zapytania sqlalchemy, w jaki sposób zakodowałbym zapytanie (nie ma .encode, ponieważ nie jest to ciąg)?
c8999c 3f964f64
129

Zmieniłem to po prostu definiując inny pakiet kodeków w read_csv()poleceniu:

encoding = 'unicode_escape'

Na przykład:

import pandas as pd
data = pd.read_csv(filename, encoding= 'unicode_escape')
Salty
źródło
1
Tylko jeśli używaszpandas
Valeriy
1
przepraszam, to nie zadziałało, znowu miałem ten sam błąd. ale kiedy użyłem ('filename.csv', engine = 'python'). To zadziałało.
basavaraj_S
117

Wypróbuj poniższy fragment kodu:

with open(path, 'rb') as f:
  text = f.read()
Koral
źródło
7
Miałem rzamiast rb. dzięki za przypomnienie o dodaniu b!
Paul
1
Domyślnie openfunkcja ma „r” jako tryb tylko do odczytu. rboznacza tryb odczytu binarnego.
shiva
39

Twój ciąg zawiera niezakodowany asciiznak.

Brak możliwości dekodowania za pomocą utf-8może się zdarzyć, jeśli musisz użyć innego kodowania w swoim kodzie. Na przykład:

>>> 'my weird character \x96'.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x96 in position 19: invalid start byte

W takim przypadku kodowanie jest windows-1252takie, że musisz to zrobić:

>>> 'my weird character \x96'.decode('windows-1252')
u'my weird character \u2013'

Teraz, gdy już to zrobiłeś Unicode, możesz bezpiecznie kodować do utf-8.

JCF
źródło
1
Stworzyłem prostą stronę, która może pomóc w ustaleniu kodowania niektórych nieoczekiwanych „tajemniczych bajtów”; tripleee.github.io/8bit
tripleee
34

Podczas czytania csvdodałem metodę kodowania:

import pandas as pd
dataset = pd.read_csv('sample_data.csv', header= 0,
                        encoding= 'unicode_escape')
Krishna prasad.m
źródło
16

Ustaw domyślny koder u góry kodu

import sys
reload(sys)
sys.setdefaultencoding("ISO-8859-1")
HimalayanCoder
źródło
Myślę, że python3 nie ma setdefaultencoding w module sys!
Anwar Hossain
14

Od 2018-05 jest to obsługiwane bezpośrednio decode, przynajmniej w przypadku Pythona 3 .

Używam poniższego fragmentu kodu invalid start bytei invalid continuation bytewpisuję błędy. Dodanie errors='ignore'naprawiło to dla mnie.

with open(out_file, 'rb') as f:
    for line in f:
        print(line.decode(errors='ignore'))
aaronpenne
źródło
1
Oczywiście to po cichu odrzuca informacje. Znacznie lepszym rozwiązaniem jest ustalenie, co powinno tam być i naprawienie pierwotnego problemu.
tripleee
14

Zainspirowany @aaronpenne i @Soumyaansh

f = open("file.txt", "rb")
text = f.read().decode(errors='replace')
Punnerud
źródło
Otrzymałem „AttributeError: 'str' obiekt nie ma atrybutu 'decode'”. Nie wiesz, co poszło nie tak?
Victor Wong,
Czy dołączyłeś b do „rb”? Litera b służy do otwierania pliku w formacie bajtowym. Jeśli użyjesz po prostu r, jest to łańcuch i nie uwzględniaj dekodowania.
Punnerud,
14

To rozwiązanie zadziałało dla mnie:

import pandas as pd
data = pd.read_csv("training.csv", encoding = 'unicode_escape')
siedmiodniowa żałoba
źródło
11

Proste rozwiązanie:

import pandas as pd
df = pd.read_csv('file_name.csv', engine='python')
Gil Baggio
źródło
3
Dzięki, że pomogłem!
Ruben
Cieszę się, że mogłem pomóc @ Ruben
Gil Baggio
2
Dziękuję, że mi to pomogło. Pracowałem nad pandami.
Jeszcze
Chętnie pomogę @basavaraj_S
Gil Baggio
1
Jedyne rozwiązanie, które mi odpowiada spośród wszystkich prezentowanych tutaj.
lunesco
7

Poniższy wiersz szkodzi koderowi JSON,

now = datetime.datetime.now()
now = datetime.datetime.strftime(now, '%Y-%m-%dT%H:%M:%S.%fZ')
print json.dumps({'current_time': now}) // this is the culprit

Mam tymczasową poprawkę

print json.dumps( {'old_time': now.encode('ISO-8859-1').strip() })

Oznaczanie tego jako poprawnego jako tymczasowa poprawka (nie jestem pewien).

Deepak Ingole
źródło
5

Jeśli powyższe metody nie działają dla Ciebie, możesz chcieć zmienić kodowanie samego pliku csv.

Korzystanie z programu Excel:

  1. Otwórz plik CSV za pomocą programu Excel
  2. Przejdź do opcji „menu Plik” i kliknij „Zapisz jako”
  3. Kliknij „Przeglądaj”, aby wybrać lokalizację, w której chcesz zapisać plik
  4. Wprowadź zamierzoną nazwę pliku
  5. Wybierz opcję CSV (rozdzielany przecinkami) (* .csv)
  6. Kliknij menu rozwijane „Narzędzia” i kliknij „Opcje internetowe”
  7. Na karcie „Kodowanie” wybierz opcję Unicode (UTF-8) z listy rozwijanej „Zapisz ten dokument jako”
  8. Zapisz plik

Korzystanie z Notatnika:

  1. Otwórz plik csv za pomocą notatnika
  2. Przejdź do opcji „Plik”> „Zapisz jako”
  3. Następnie wybierz lokalizację pliku
  4. Wybierz opcję Zapisz jako typ jako Wszystkie pliki ( . )
  5. Określ nazwę pliku z rozszerzeniem .csv
  6. Z listy rozwijanej „Kodowanie” wybierz opcję UTF-8.
  7. Kliknij Zapisz, aby zapisać plik

Robiąc to, powinieneś być w stanie importować pliki csv bez napotkania UnicodeCodeError.

Zuo
źródło
2

Po wypróbowaniu wszystkich wyżej wymienionych obejść, jeśli nadal generuje ten sam błąd, możesz spróbować wyeksportować plik jako CSV (drugi raz, jeśli już masz). Szczególnie jeśli używasz scikit Learn, najlepiej zaimportować zbiór danych jako plik CSV.

Spędziłem razem godziny, a rozwiązanie było takie proste. Wyeksportuj plik jako plik CSV do katalogu, w którym jest zainstalowany program Anaconda lub narzędzia klasyfikatora, i spróbuj.

Sushmita
źródło
2

Możesz użyć dowolnego standardowego kodowania określonego zastosowania i danych wejściowych.

utf-8 jest wartością domyślną.

iso8859-1 jest również popularny w Europie Zachodniej.

na przykład: bytes_obj.decode('iso8859-1')

zobacz: docs

NoamG
źródło
1
Ślepe odgadnięcie kodowania może spowodować więcej błędów. Wybranie iso8859-1 lub cp1251 itp. Bez faktycznej wiedzy, jakiego kodowania używa plik, usunie symptomy, ale spowoduje powstanie śmieci, jeśli zgadłeś źle. Jeśli to tylko kilka bajtów, może minąć lata, zanim zauważysz i naprawisz prawdziwy błąd.
tripleee