Mam problemy z obsługą znaków Unicode z tekstu pobranego z różnych stron internetowych (na różnych stronach). Używam BeautifulSoup.
Problem polega na tym, że błąd nie zawsze jest powtarzalny; czasami działa z niektórymi stronami, a czasem obrzuca, rzucając UnicodeEncodeError
. Próbowałem prawie wszystkiego, co mogłem wymyślić, a jednak nie znalazłem niczego, co działałoby konsekwentnie bez zgłaszania jakiegoś błędu związanego z Unicode.
Jedna z sekcji kodu, która powoduje problemy, pokazano poniżej:
agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
Oto ślad stosu wygenerowany na NIEKTÓRYCH ciągach znaków po uruchomieniu powyższego fragmentu:
Traceback (most recent call last):
File "foobar.py", line 792, in <module>
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)
Podejrzewam, że dzieje się tak, ponieważ niektóre strony (a ściślej strony z niektórych witryn) mogą być kodowane, podczas gdy inne mogą być zakodowane. Wszystkie strony mają siedzibę w Wielkiej Brytanii i dostarczają dane przeznaczone do konsumpcji w Wielkiej Brytanii - więc nie ma żadnych problemów związanych z internalizacją lub obsługą tekstu napisanego w języku innym niż angielski.
Czy ktoś ma jakieś pomysły, jak to rozwiązać, abym ZGODNIE rozwiązał ten problem?
źródło
import os; import locale; os.environ["PYTHONIOENCODING"] = "utf-8"; myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8"); ... print(myText.encode('utf-8', errors='ignore'))
.$ export PYTHONIOENCODING=utf8
Odpowiedzi:
Musisz przeczytać HOWTO w języku Python Unicode . Ten błąd jest pierwszym przykładem .
Zasadniczo przestań używać
str
do konwersji z Unicode na zakodowany tekst / bajty.Zamiast tego należy poprawnie użyć
.encode()
do zakodowania ciągu:lub pracować całkowicie w trybie Unicode.
źródło
print
ciągi utf-8, działa dobrze. Jednak gdy potokuję dane wyjściowe mojego programu do pliku, wyrzuca toUnicodeEncodeError
. W rzeczywistości, gdy dane wyjściowe są przekierowywane (do pliku lub potoku), stwierdzam, żesys.stdout.encoding
takNone
! Halsowanie.encode('utf-8')
rozwiązuje problem.PYTHONIOENCODING=utf-8
zamiast tego użyj, tzn. wypisz ciągi Unicode i pozwól środowisku ustawić oczekiwane kodowanie..encode()
metody do wywołania.Jest to klasyczny punkt bólu unicode u pytona! Rozważ następujące:
Jak dotąd wszystko dobrze, ale jeśli nazwiemy str (a), zobaczmy, co się stanie:
Och, dip, to nikomu nie pomoże! Aby naprawić błąd, koduj bajty jawnie za pomocą .encode i powiedz pythonowi, jakiego kodeka użyć:
Voil \ u00E0!
Problem polega na tym, że kiedy wywołujesz str (), python używa domyślnego kodowania znaków, aby spróbować zakodować podane bajty, które w twoim przypadku są czasami reprezentacją znaków Unicode. Aby rozwiązać problem, musisz powiedzieć pythonowi, jak postępować z podanym ciągiem znaków, używając .encode („cokolwiek_kod”). Przez większość czasu powinieneś być w porządku, używając utf-8.
Doskonałą prezentację na ten temat można znaleźć w wykładzie PyCon Neda Batcheldera tutaj: http://nedbatchelder.com/text/unipain.html
źródło
None
wartością.Znalazłem elegancką metodę usuwania symboli i kontynuowania ciągów znaków w następujący sposób:
Ważne jest, aby zauważyć, że użycie opcji ignorowania jest niebezpieczne, ponieważ po cichu usuwa obsługę Unicode (i internacjonalizacji) z kodu, który go używa, jak pokazano tutaj (konwersja Unicode):
źródło
yourstring = yourstring.encode('utf-8', 'ignore').decode('utf-8')
os.path.join()
, jest to bardzo dobry nawyk, kiedy zaczynasz programować na wielu platformach. :)cóż, próbowałem wszystkiego, ale to nie pomogło, po googlowaniu doszedłem do wniosku, że to pomogło. Python 2.7 jest w użyciu.
źródło
if sys.version_info.major < 3:
Subtelnym problemem powodującym nawet awarię drukowania jest nieprawidłowe ustawienie zmiennych środowiskowych, np. tutaj LC_ALL ustawione na „C”. W Debianie odradzają ustawianie: Debian wiki w Locale
źródło
env|grep -E '(LC|LANG)'
.mc
w trybie „podpowłoki” (Ctrl-O
) i ja też zapomniałem, że dodałem następujące aliasu bash:alias mc="LANG=en_EN.UTF-8 mc"
. Więc kiedy próbowałem uruchomić źle napisane skrypty, które opierają się naru_RU.UTF-8
wewnętrznej stronie, po prostu umierają. Próbowałem wiele rzeczy z tego wątku, zanim odkryłem prawdziwy problem. :)Dla mnie zadziałało:
Mam nadzieję, że to komuś pomoże.
źródło
Przekonałem się, że w większości przypadków usunięcie tych postaci jest znacznie prostsze:
źródło
Problem polega na tym, że próbujesz wydrukować znak Unicode, ale twój terminal go nie obsługuje.
Możesz spróbować zainstalować
language-pack-en
pakiet, aby to naprawić:który zapewnia aktualizacje danych tłumaczeń na język angielski dla wszystkich obsługiwanych pakietów (w tym Python). W razie potrzeby zainstaluj inny pakiet językowy (w zależności od znaków, które próbujesz wydrukować).
W niektórych dystrybucjach Linuksa jest to wymagane, aby upewnić się, że domyślne ustawienia narodowe w języku angielskim są poprawnie skonfigurowane (aby znaki Unicode mogły być obsługiwane przez powłokę / terminal). Czasami łatwiej jest go zainstalować, niż konfigurować go ręcznie.
Następnie, pisząc kod, upewnij się, że używasz odpowiedniego kodowania w kodzie.
Na przykład:
Jeśli nadal masz problem, sprawdź dwukrotnie konfigurację systemu, na przykład:
Twój plik ustawień regionalnych (
/etc/default/locale
), który powinien mieć nplub:
Wartość
LANG
/LC_CTYPE
w powłoce.Sprawdź, jakie ustawienia regionalne obsługuje Twoja powłoka:
Demonstracja problemu i rozwiązania w nowej maszynie wirtualnej.
Zainicjuj i zainicjuj maszynę wirtualną (np. Za pomocą
vagrant
):Zobacz: dostępne pudełka Ubuntu . .
Drukowanie znaków Unicode (takich jak znak towarowy, jak
™
):Teraz instaluję
language-pack-en
:Teraz problem powinien zostać rozwiązany:
W przeciwnym razie spróbuj wykonać następujące polecenie:
źródło
language-pack-en
ma wspólnego z Pythonem lub tym pytaniem? AFAIK, może zapewniać tłumaczenia językowe wiadomości, ale nie ma nic wspólnego z kodowaniem/etc/locale.gen
aby upewnić się, że jego ustawienia narodowe zostały zbudowane przed użyciem?LANG
z/etc/default/locale
(jak/etc/locale.gen
exist does't) i pobiegłlocale-gen
, ale to nie pomogło. Nie jestem pewien, colanguage-pack-en
dokładnie robi, ponieważ nie znalazłem dużo dokumentacji, a spisanie jej treści niewiele pomaga.LANG
/LC_CTYPE
/LC_ALL
zamiast (npLANG=C.UTF-8
.).W skorupkach:
Znajdź obsługiwane ustawienia narodowe UTF-8 za pomocą następującego polecenia:
Wyeksportuj go przed uruchomieniem skryptu, np .:
lub ręcznie jak:
Sprawdź to, drukując znak specjalny, np .
™
:Powyżej testowane w Ubuntu.
źródło
Dodaj wiersz poniżej na początku skryptu (lub jako drugi wiersz):
To jest definicja kodowania kodu źródłowego Pythona. Więcej informacji w PEP 263 .
źródło
Oto przegląd niektórych innych tak zwanych odpowiedzi „wykopać”. Są sytuacje, w których po prostu wyrzucenie kłopotliwych znaków / sznurków jest dobrym rozwiązaniem, pomimo wyrażonych tutaj protestów.
Testowanie:
Wyniki:
Wskazówka:
toAscii
zamiast tego możesz nazwać tę funkcję ? To kwestia preferencji.Zostało to napisane dla Python 2. Dla Python 3, myślę, że będziesz chciał użyć
bytes(obj,"ascii")
zamiaststr(obj)
. Jeszcze tego nie przetestowałem, ale w pewnym momencie zmienię odpowiedź.źródło
Zawsze umieszczam poniższy kod w pierwszych dwóch wierszach plików Pythona:
źródło
Znaleziono tutaj proste funkcje pomocnicze .
źródło
backslashreplace
obsługi błędu:u'\xa0'.encode('ascii', 'backslashreplace')
. Chociaż powinieneś unikać takiej reprezentacji i skonfigurować środowisko tak, aby akceptowało znaki inne niż ascii - jest 2016!Po prostu dodaj do kodu zmiennej („utf-8”)
źródło
Otwórz terminal i uruchom poniższe polecenie:
źródło
Właśnie użyłem następujących:
Sprawdź, co mówi o tym dokumentacja:
Rozwiązuje to dla mnie. Proste i łatwe.
źródło
Poniższe rozwiązanie działało dla mnie, właśnie dodane
(reprezentujący ciąg jako Unicode) przed moim ciągiem.
źródło
Niestety działa to w Pythonie 3 przynajmniej ...
Python 3
Czasami błąd występuje w zmiennych środowiskowych i zawiera się w nich
gdzie błędy są ignorowane w kodowaniu.
źródło
Właśnie miałem ten problem i Google zaprowadził mnie tutaj, więc aby dodać tutaj ogólne rozwiązania, oto, co zadziałało dla mnie:
Wpadłem na ten pomysł po przeczytaniu prezentacji Neda .
Nie twierdzę jednak, że w pełni rozumiem, dlaczego to działa. Jeśli więc ktoś może edytować tę odpowiedź lub umieścić komentarz w celu wyjaśnienia, docenię to.
źródło
type
wartość? przed i po tym? Myślę, że to działa, robiącunic += value
to samo, counic = unic + value
dodajesz ciąg znaków i Unicode, przy czym Python zakłada Unicode dla wynikowego,unic
tj. Bardziej precyzyjnego typu (pomyśl o tym, gdy to zrobisza = float(1) + int(1)
,a
staje się zmiennoprzecinkowe) i następnievalue = unic
wskazujevalue
nowyunic
obiekt, którym jest Unicode.Wystąpił ten błąd podczas uruchamiania
manage.py migrate
w Django ze zlokalizowanymi urządzeniami.Nasze źródło zawierało
# -*- coding: utf-8 -*-
deklarację, MySQL został poprawnie skonfigurowany dla utf8, a Ubuntu miał odpowiedni pakiet językowy i wartości/etc/default/locale
.Problem polegał na tym, że w kontenerze Django (używamy Dockera) brakowało
LANG
zmiennej env.Ustawianie
LANG
sięen_US.UTF-8
i ponownym uruchomieniu pojemnik przed ponownym uruchomieniem migracje rozwiązaniu problemu.źródło
Wiele odpowiedzi tutaj (na przykład @agf i @Andbdrew) odnosiło się już do najbardziej bezpośrednich aspektów pytania PO.
Myślę jednak, że istnieje jeden subtelny, ale ważny aspekt, który został w dużej mierze zignorowany i który ma duże znaczenie dla każdego, kto jak ja, skończył tutaj, próbując zrozumieć kodowanie w Pythonie: zarządzanie reprezentacją znaków w Python 2 vs Python 3 jest zupełnie inne . Wydaje mi się, że duża część zamieszania dotyczy ludzi czytających o kodowaniu w Pythonie bez świadomości wersji.
Sugeruję, aby każdy zainteresowany zrozumieniem przyczyny problemu OP zaczął od przeczytania wstępu Spolsky'ego do reprezentacji znaków i Unicode, a następnie przeniósł się do Batcheldera na Unicode w Python 2 i Python 3.
źródło
Staraj się unikać konwersji zmiennej na str (zmienna). Czasami może to powodować problem.
Prosta wskazówka, której należy unikać:
Powyższy przykład rozwiąże również błąd kodowania.
źródło
Jeśli masz coś takiego,
packet_data = "This is data"
zrób to w następnym wierszu, zaraz po zainicjowaniupacket_data
:źródło
Aktualizacja dla Python 3.0 i nowszych. Spróbuj wykonać następujące czynności w edytorze python:
Ustawia to domyślne kodowanie ustawień regionalnych systemu na format UTF-8.
Więcej można przeczytać tutaj w PEP 538 - Wymuszanie starszej wersji języka C na lokalizację opartą na UTF-8 .
źródło
Miałem ten problem, próbując wypisać znaki Unicode
stdout
, ale zsys.stdout.write
zamiast, zamiast drukować (aby móc obsługiwać również wyjście do innego pliku).Z własnej dokumentacji BeautifulSoup rozwiązałem to za pomocą biblioteki kodeków:
źródło
Ten problem często występuje, gdy projekt django wdraża się przy użyciu Apache. Ponieważ Apache ustawia zmienną środowiskową LANG = C w / etc / sysconfig / httpd. Po prostu otwórz plik i skomentuj (lub zmień swój styl) to ustawienie. Lub użyj opcji lang komendy WSGIDaemonProcess, w takim przypadku będziesz mógł ustawić inną zmienną środowiskową LANG dla różnych wirtualnych hostów.
źródło
Zalecane rozwiązanie nie działało dla mnie i mogłem żyć z odrzucaniem wszystkich postaci nie ascii, więc
co pozostawiło mi coś rozebranego, co nie powoduje błędów.
źródło
To zadziała:
Wynik:
źródło