2010-08-13 13 views
10

Czytam w pliku z modułem Pythona csv i mam jeszcze inne pytanie dotyczące kodowania (przepraszam, jest ich tu wiele).Python csv: UnicodeDecodeError

W pliku CSV są znaki £. Po przeczytaniu wiersza i wydrukowaniu stały się \ xa3.

Próbując zakodować je jako Unicode wytwarza UnicodeDecodeError:

row = [unicode(x.strip()) for x in row] 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa3 in position 0: ordinal not in range(128) 

I zostały czytanie csv documentation i wiele innych pytań na ten temat na StackOverflow. I myślę, że to, że £ staje się \ xa3 w ASCII oznacza, że ​​oryginalny plik CSV jest w UTF-8.

(Nawiasem mówiąc, jest tam szybki sposób sprawdzić kodowanie pliku CSV?)

Jeśli jest w UTF-8, wtedy nie powinno moduł csv być w stanie poradzić sobie z tym poradzić? Wygląda na to, że wszystkie symbole są przekształcane w ASCII, mimo że dokumentacja twierdzi, że akceptuje UTF-8.

Próbowałem dodać funkcję unicode_csv_reader, jak opisano w csv examples, ale to nie pomaga.

---- EDIT -----

I powinna wyjaśnić jedną rzecz. Widziałem this question, który wygląda bardzo podobnie. Ale dodanie funkcji unicode_csv_reader zdefiniowane tam produkuje inny błąd zamiast:

yield [unicode(cell, 'utf-8') for cell in row] 
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa3 in position 8: unexpected code byte 

Więc może mój plik nie jest UTF8 po wszystkim? Jak mogę to powiedzieć?

Odpowiedz

7

Spróbuj użyć "ISO-8859-1" do kodowania. Wygląda na to, że masz do czynienia z rozszerzonym ASCII, a nie Unicode.

Edit:

Oto niektóre prosty kod, który zajmuje się rozszerzonym ASCII: jeszcze lepiej

>>> s = "La Pe\xf1a" 
>>> print s 
La Pe±a 
>>> print s.decode("latin-1") 
La Peña 
>>> 

, radzenia sobie z dokładnym charakterze, które daje Ci problemy:

>>> s = "12\xa3" 
>>> print s.decode("latin-1") 
12£ 
>>> 
+0

masz na myśli zastosowanie: plastyczności [Unicode (komórki „ISO-8859-1”) na komórki wiersz] zamiast, w funkcji unicode_csv_reader? Niestety to nie pomaga - z powrotem do błędu porządkowego nie w zasięgu (128). – AP257

+0

Nie byłoby sensu używać funkcji zwanej unicode() podczas pracy z ASCII. Chodzi o to, że mamy do czynienia z plikiem zakodowanym przy użyciu kodowania "ISO-8859-1".Nie napisałem żadnego kodu, ponieważ nie wiem, jak to zrobić z góry mojej głowy, ale twój problem polega na tym, że musisz go rozszyfrować jako ISO-8859-1, a nie Unicode. – riwalk

+0

OK, dziękuję. Zbadam. Skąd wiesz, że to był ISO-8859-1? Innymi słowy, czy istnieje sposób, aby samemu sprawdzić kodowanie, zamiast zadawać głupie pytania na temat StackOverflow :) – AP257

0

Jeśli są w systemie Windows, jest bardzo prawdopodobne, że kodowanie, którego należy użyć, jest jedną z rodziny cp125X ... np jeśli jesteś w Europie Zachodniej lub obu Amerykach, będzie to cp1252. Oprogramowanie Windows często używa bajtów w zakresie od \x80 do \x9F włącznie do kodowania fantazyjnych znaków interpunkcyjnych, podczas gdy zakres ten jest zarezerwowany w ISO-8859-X dla rzadko używanych "znaków kontrolnych C1".

Możesz dowiedzieć się zwykłe kodowanie w danym regionie, uruchamiając to w wierszu poleceń:

python -c "import locale; print locale.getpreferredencoding()" 
+0

Ma problemy z odczytywaniem znaków £ i zakładasz, że plik został zapisany w wygodny sposób przy ustawieniach * preferowanych przez jego * komputer? Byłbym ostrożny zakładając, że plik jest czymś, co zostało zapisane przy użyciu jego komputera. – riwalk

+0

@ Stargazer712: Nie, nie zakładam niczego. Sugeruję, że jest wysoce prawdopodobne, że plik został utworzony na komputerze w tych samych ustawieniach narodowych i przy użyciu tego samego systemu operacyjnego, co maszyna, z której korzysta OP. –

+0

Moje doświadczenie z kodowaniem (jak wspomniałem wcześniej) pochodziło ze skrobania sieci. Zapewniam cię, że nie jest to bezpieczne założenie. – riwalk