Próbuję pracować z bardzo dużym zbiorem danych, który zawiera kilka niestandardowych znaków. Muszę użyć Unicode, zgodnie ze specyfikacją pracy, ale jestem zdziwiony. (I całkiem możliwe, że robię to wszystko źle.)
Otwieram CSV za pomocą:
15 ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"')
Następnie próbuję zakodować go za pomocą:
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])
Koduję wszystko oprócz lat i lng, ponieważ muszą one zostać wysłane do API. Kiedy uruchamiam program, aby przeanalizować zestaw danych do tego, czego mogę użyć, otrzymuję następujący 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)
Myślę, że powinienem powiedzieć, że używam Pythona 2.7.2 i jest to część aplikacji zbudowanej na django 1.4. Przeczytałem kilka postów na ten temat, ale żaden z nich nie wydaje się mieć bezpośredniego zastosowania. Każda pomoc będzie bardzo mile widziana.
Możesz również chcieć wiedzieć, że niektóre niestandardowe znaki powodujące problem to Ñ i prawdopodobnie É.
Odpowiedzi:
Unicode nie jest równy UTF-8. To drugie jest tylko kodowaniem dla pierwszego.
Robisz to w niewłaściwy sposób. Jesteś czytanie UTF-8 zakodowane dane, więc trzeba dekodowania UTF-8 zakodowany ciąg na ciąg znaków Unicode.
Więc po prostu zastąpić
.encode
z.decode
, i to powinno działać (jeśli .csv jest UTF-8-zakodowane).Nie ma się jednak czego wstydzić. Założę się, że 3 na 5 programistów miało na początku problemy ze zrozumieniem tego, jeśli nie więcej;)
Aktualizacja: Jeśli twoje dane wejściowe nie są zakodowane w UTF-8, musisz
.decode()
oczywiście z odpowiednim kodowaniem. Jeśli nic nie zostanie podane, python zakłada ASCII, co oczywiście kończy się niepowodzeniem w przypadku znaków innych niż ASCII.źródło
.decode('utf-8')
powinno załatwić sprawę , ani?Po prostu dodaj te linie do swoich kodów:
źródło
dla użytkowników Pythona 3. możesz to zrobić
działa też z kolbą :)
źródło
Głównym powodem błędu jest to, że domyślnym kodowaniem przyjętym przez Pythona jest ASCII. W związku z tym, jeśli dane ciągu, które mają być zakodowane,
encode('utf8')
zawierają znak spoza zakresu ASCII, np. Dla łańcucha takiego jak „hgvcj 터 파크 387”, Python zgłosi błąd, ponieważ łańcuch nie jest w oczekiwanym formacie kodowania.Jeśli używasz wersji Pythona wcześniejszej niż 3.5, niezawodną poprawką byłoby ustawienie domyślnego kodowania przyjętego przez Pythona na
utf8
:W ten sposób Python byłby w stanie przewidzieć znaki w ciągu, które wykraczają poza zakres ASCII.
Jeśli jednak używasz Pythona w wersji 3.5 lub nowszej, funkcja reload () nie jest dostępna, więc musiałbyś to naprawić za pomocą dekodowania, np.
źródło
Dla użytkowników Python 3:
zmiana kodowania z „ascii” na „latin1” działa.
Możesz również spróbować znaleźć kodowanie automatycznie, odczytując pierwsze 10000 bajtów za pomocą poniższego fragmentu:
źródło
Mój komputer miał ustawione niewłaściwe ustawienia regionalne.
Ja pierwszy
locale.getpreferredencoding(False)
jest funkcją wywoływaną przez,open()
gdy nie podajesz kodowania . Wyjście powinno być'UTF-8'
, ale w tym przypadku jest to jakiś wariant ASCII .Następnie uruchomiłem polecenie bash
locale
i otrzymałem to wyjścieTak więc korzystałem z domyślnych ustawień regionalnych Ubuntu, co powoduje, że Python otwiera pliki jako ASCII zamiast UTF-8. Musiałem ustawić ustawienia regionalne na
en_US.UTF-8
Jeśli nie możesz zmienić ustawień regionalnych w całym systemie, możesz wywołać cały kod Pythona w następujący sposób:
lub zrób
aby ustawić go w powłoce, w której to uruchomisz.
źródło
Jeśli napotkasz ten problem podczas uruchamiania certbot podczas tworzenia lub odnawiania certyfikatu, użyj następującej metody
grep -r -P '[^\x00-\x7f]' /etc/apache2 /etc/letsencrypt /etc/nginx
To polecenie znalazło obraźliwy znak „´” w jednym pliku .conf w komentarzu. Po usunięciu go (możesz edytować komentarze, jak chcesz) i przeładowaniu nginx, wszystko działało ponownie.
Źródło: https://github.com/certbot/certbot/issues/5236
źródło
Lub kiedy masz do czynienia z tekstem w Pythonie, jeśli jest to tekst Unicode, zanotuj, że jest to Unicode.
text=u'unicode text'
Zamiast tego ustaw po prostutext='unicode text'
.To zadziałało w moim przypadku.
źródło
otwarte z kodowaniem UTF 16 ze względu na szerokość i długość.
źródło
Działa po prostu przyjmując argument „rb” do odczytu binarnego zamiast „r” do odczytu
źródło