UnicodeEncodeError: Kodek „ascii” nie może zakodować znaku u '\ xa0' na pozycji 20: porządek poza zakresem (128)

1296

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?

Homunculus Reticulli
źródło
1
Jeśli otrzymujesz te błędy jako użytkownik, a nie jako programista, sprawdź serverfault.com/questions/54591/... i askubuntu.com/questions/599808/...
Ten Brazylijczyk Guy
Dodam ten punkt, nie używaj onlinegdb.com/online_python_interpreter do tych rzeczy. Używał tego interpretera do wypróbowywania rzeczy i nie jest poprawnie skonfigurowany dla Unicode! Zawsze drukowałem w formacie „B” \ nnn ... ... kiedy wszystko, czego chciałem, to gilemet! Wypróbowałem na maszynie wirtualnej i działała natychmiast zgodnie z oczekiwaniami za pomocą chr ()
JGFMK,
4
Spróbuj tego 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')).
hhh
@ hhh Uruchomiłem Twój fragment NameError: nazwa „myText” nie jest zdefiniowana
KHAN irfan
9
Przed uruchomieniem skryptu spróbuj ustawić PYTHONIOENCODING w powłoce:$ export PYTHONIOENCODING=utf8
Noam Manos

Odpowiedzi:

1361

Musisz przeczytać HOWTO w języku Python Unicode . Ten błąd jest pierwszym przykładem .

Zasadniczo przestań używać strdo konwersji z Unicode na zakodowany tekst / bajty.

Zamiast tego należy poprawnie użyć .encode()do zakodowania ciągu:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

lub pracować całkowicie w trybie Unicode.

agf
źródło
23
Zgoda! dobrą zasadą, której mnie nauczono, jest użycie idei „kanapki z Unicode”. Twój skrypt akceptuje bajty ze świata zewnętrznego, ale wszystkie przetwarzanie powinno odbywać się w standardzie Unicode. Tylko wtedy, gdy jesteś gotowy do wysłania danych, należy je ponownie zapisać w bajtach!
Andbdrew
256
W przypadku, gdy ktoś się tym pomyli, znalazłem dziwną rzecz: mój terminal używa utf-8, a kiedy mam printciągi utf-8, działa dobrze. Jednak gdy potokuję dane wyjściowe mojego programu do pliku, wyrzuca to UnicodeEncodeError. W rzeczywistości, gdy dane wyjściowe są przekierowywane (do pliku lub potoku), stwierdzam, że sys.stdout.encodingtak None! Halsowanie .encode('utf-8')rozwiązuje problem.
drevicko
93
@drevicko: PYTHONIOENCODING=utf-8zamiast tego użyj, tzn. wypisz ciągi Unicode i pozwól środowisku ustawić oczekiwane kodowanie.
jfs
1
@steinar: nic nie jest ważne w każdym przypadku. Ogólnie rzecz biorąc, użytkownik nie powinien przejmować się tym, że używasz Pythona do implementacji swojego narzędzia (interfejs nie powinien ulec zmianie, jeśli z jakiegokolwiek powodu zdecydujesz się na jego zaimplementowanie w innym języku), a zatem nie powinieneś oczekiwać, że ten użytkownik nawet wie o python- określone envvary. Zły interfejs użytkownika zmusza użytkownika do określenia kodowania znaków; w razie potrzeby osadzić kodowanie znaków w formacie raportu. Uwaga: kodowanie na stałe nie może być „rozsądnym domyślnym” w ogólnym przypadku.
jfs,
13
To zła i myląca rada. Powodem dla którego ludzie używają str jest to, że obiekt NIE JEST już ciągiem, więc nie ma .encode()metody do wywołania.
Cerin,
433

Jest to klasyczny punkt bólu unicode u pytona! Rozważ następujące:

a = u'bats\u00E0'
print a
 => batsà

Jak dotąd wszystko dobrze, ale jeśli nazwiemy str (a), zobaczmy, co się stanie:

str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

Och, dip, to nikomu nie pomoże! Aby naprawić błąd, koduj bajty jawnie za pomocą .encode i powiedz pythonowi, jakiego kodeka użyć:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

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

Andbdrew
źródło
85
Uwaga osobista: przy próbie wpisania „.encode” nie wpisuj przypadkowo „.unicode”, a następnie zastanawiaj się, dlaczego nic nie działa.
Pomiń Huffman,
9
Dobra rada. Ale co robisz zamiast tego, gdy używasz str (x) do drukowania obiektów, które mogą, ale nie muszą być łańcuchami? str (x) działa, jeśli x jest liczbą, datą, wartością logiczną lub normalną. Nagle, jeśli jest to Unicode, przestaje działać. Czy istnieje sposób na uzyskanie tego samego zachowania, czy też musimy teraz dodać czek IF, aby sprawdzić, czy obiekt jest ciągiem znaków, aby użyć .encode i str () w przeciwnym razie?
Dirk R
To samo pytanie można zadać z Nonewartością.
Vadorequest,
210

Znalazłem elegancką metodę usuwania symboli i kontynuowania ciągów znaków w następujący sposób:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

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):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'
Max Korolevsky
źródło
17
Sprawiłeś, że mój dzień! W przypadku utf-8 wystarczy:yourstring = yourstring.encode('utf-8', 'ignore').decode('utf-8')
luca76
dla mnie to działało, ale mój przypadek był inny, zapisywałem nazwy plików i miałem „/” w nazwie, a ścieżka nie istniała, więc muszę użyć .replace („/”, „”) i w ten sposób zapisałem mój skrypt. ignorowanie ascii działa również w przypadku „utf-8”.
Akash Kandpal
1
@ harrypotter0 do prawidłowego korzystania ze ścieżek plików os.path.join(), jest to bardzo dobry nawyk, kiedy zaczynasz programować na wielu platformach. :)
login_not_failed
152

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.

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
Ashwin
źródło
7
Nie rób tego stackoverflow.com/questions/3828723/… , chociaż kiedy masz odpowiedzi takie jak stackoverflow.com/a/31137935/2141635 u góry wyników, gdy szukasz błędu, widzę, dlaczego może to wydawać się dobrym pomysłem.
Padraic Cunningham,
21
Wypróbowałem prawie wszystkie sugestie w tym temacie i tak naprawdę żadna z nich nie zadziałała. W końcu spróbowałem tego. I to naprawdę JEDYNE, co działało prosto i dobrze. Jeśli ktoś powie: „Nie rób tego, skorzystaj z prostego rozwiązania. W przeciwnym razie skorzystaj z tego. Ponieważ jest to dobra kopia robocza i poprzednie rozwiązanie.
Richard de Ree
4
Jak można to zrobić w python3? Byłbym szczęśliwy wiedząc.
Kanerva Peter
3
Po tylu frustracjach ten zadziałał. Wielkie dzięki.
Avraham Zhurba,
4
Dodałbym tylkoif sys.version_info.major < 3:
umowa prof. Falkena została naruszona
87

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

$ echo $LANG
en_US.utf8
$ echo $LC_ALL 
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà
maxpolk
źródło
Mam dokładnie ten sam problem, więc źle, że nie sprawdziłem go przed zgłoszeniem . Wielkie dzięki. Nawiasem mówiąc, możesz zamienić pierwsze dwa polecenia na env|grep -E '(LC|LANG)'.
Dmitrij Verhoturov
Tylko moje dwa centy za niewłaściwe kodowanie. I często używać mcw 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ę na ru_RU.UTF-8wewnętrznej stronie, po prostu umierają. Próbowałem wiele rzeczy z tego wątku, zanim odkryłem prawdziwy problem. :)
login_not_failed
JESTEŚ NIESAMOWITY. W GSUTIL mój rsync zawiódł z powodu dokładnie tego problemu. Naprawiono LC_ALL i wszystko działa dobrze jak wino. <3 DZIĘKUJEMY <3
dsignr
27

Dla mnie zadziałało:

BeautifulSoup(html_text,from_encoding="utf-8")

Mam nadzieję, że to komuś pomoże.

Animesh
źródło
25

Przekonałem się, że w większości przypadków usunięcie tych postaci jest znacznie prostsze:

s = mystring.decode('ascii', 'ignore')
Phil LaNasa
źródło
26
„Idealnie” zwykle nie jest tym, co wykonuje. Wyrzuca rzeczy, z którymi powinieneś dowiedzieć się, jak sobie z tym poradzić.
tripleee
7
samo usunięcie „tych” (nieangielskich) znaków nie jest rozwiązaniem, ponieważ python musi obsługiwać wszystkie języki, nie sądzisz?
alemol
8
Doceniony. To wcale nie jest właściwe rozwiązanie. Dowiedz się, jak pracować z Unicode: joelonsoftware.com/articles/Unicode.html
Andrew Ferrier
4
Spójrz, najbardziej rozsądny sposób na przedstawienie tej konkretnej odpowiedzi jest następujący: uznanie, że ascii przyznaje określony przywilej określonym językom i użytkownikom - jest to właz ewakuacyjny, który można wykorzystać dla tych użytkowników, którzy mogą włamać się do pobieżnego, pierwszego przejścia , skrypt razem potencjalnie do wstępnej pracy przed wdrożeniem pełnej obsługi Unicode.
lol
5
Jeśli piszę skrypt, który musi tylko wydrukować tekst w języku angielskim na standardowe wyjście w wewnętrznej aplikacji firmy, chcę tylko, aby problem zniknął. Cokolwiek działa.
kagronick
25

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-enpakiet, aby to naprawić:

sudo apt-get install language-pack-en

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:

open(foo, encoding='utf-8')

Jeśli nadal masz problem, sprawdź dwukrotnie konfigurację systemu, na przykład:

  • Twój plik ustawień regionalnych ( /etc/default/locale), który powinien mieć np

    LANG="en_US.UTF-8"
    LC_ALL="en_US.UTF-8"

    lub:

    LC_ALL=C.UTF-8
    LANG=C.UTF-8
  • Wartość LANG/ LC_CTYPEw powłoce.

  • Sprawdź, jakie ustawienia regionalne obsługuje Twoja powłoka:

    locale -a | grep "UTF-8"

Demonstracja problemu i rozwiązania w nowej maszynie wirtualnej.

  1. Zainicjuj i zainicjuj maszynę wirtualną (np. Za pomocą vagrant):

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh

    Zobacz: dostępne pudełka Ubuntu . .

  2. Drukowanie znaków Unicode (takich jak znak towarowy, jak ):

    $ python -c 'print(u"\u2122");'
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
  3. Teraz instaluję language-pack-en:

    $ sudo apt-get -y install language-pack-en
    The following extra packages will be installed:
      language-pack-en-base
    Generating locales...
      en_GB.UTF-8... /usr/sbin/locale-gen: done
    Generation complete.
  4. Teraz problem powinien zostać rozwiązany:

    $ python -c 'print(u"\u2122");'
    
  5. W przeciwnym razie spróbuj wykonać następujące polecenie:

    $ LC_ALL=C.UTF-8 python -c 'print(u"\u2122");'
    
kenorb
źródło
1
Co to language-pack-enma 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
Alastair McCormack
2
W niektórych dystrybucjach Linuksa jest to wymagane, aby upewnić się, że domyślne ustawienia narodowe w języku angielskim są poprawnie skonfigurowane, szczególnie podczas uruchamiania skryptu Python na terminalu. W pewnym momencie zadziałało to dla mnie. Zobacz: kodowanie znaków
kenorb,
Ach, okej Masz na myśli, jeśli chcesz używać ustawień narodowych innych niż angielski? Wydaje mi się, że użytkownik będzie musiał także edytować, /etc/locale.genaby upewnić się, że jego ustawienia narodowe zostały zbudowane przed użyciem?
Alastair McCormack,
1
@AlastairMcCormack wykomentowane LANGz /etc/default/locale(jak /etc/locale.genexist does't) i pobiegł locale-gen, ale to nie pomogło. Nie jestem pewien, co language-pack-endokładnie robi, ponieważ nie znalazłem dużo dokumentacji, a spisanie jej treści niewiele pomaga.
kenorb
1
jest mało prawdopodobne, że w systemie stacjonarnym nie ma już żadnych ustawień narodowych utf-8, tzn. prawdopodobnie nie trzeba niczego instalować, wystarczy skonfigurować LANG/ LC_CTYPE/ LC_ALLzamiast (np LANG=C.UTF-8.).
jfs
19

W skorupkach:

  1. Znajdź obsługiwane ustawienia narodowe UTF-8 za pomocą następującego polecenia:

    locale -a | grep "UTF-8"
  2. Wyeksportuj go przed uruchomieniem skryptu, np .:

    export LC_ALL=$(locale -a | grep UTF-8)

    lub ręcznie jak:

    export LC_ALL=C.UTF-8
  3. Sprawdź to, drukując znak specjalny, np . :

    python -c 'print(u"\u2122");'

Powyżej testowane w Ubuntu.

kenorb
źródło
Tak, to najlepsza krótka odpowiedź, nie możemy zmodyfikować kodu źródłowego, aby używał .encode
Luat Nguyen - Neo.Mxn0
16

Dodaj wiersz poniżej na początku skryptu (lub jako drugi wiersz):

# -*- coding: utf-8 -*-

To jest definicja kodowania kodu źródłowego Pythona. Więcej informacji w PEP 263 .

Andrij Ivaneyko
źródło
2
Nie rozwiązuje to problemu, gdy przetworzony tekst załadowany z pliku zewnętrznego zawiera kodowanie utf-8. Pomaga to tylko literałom napisanym w danym skrypcie Pythona i jest tylko wskazówką dla interpretera Pythona, ale nie ma wpływu na przetwarzanie tekstu.
Mikaelblomkvistsson
16

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.

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

Testowanie:

if __name__ == '__main__': 
    print safeStr( 1 ) 
    print safeStr( "test" ) 
    print u'98\xb0'
    print safeStr( u'98\xb0' )

Wyniki:

1
test
98°
98

Wskazówka: toAsciizamiast 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")zamiast str(obj). Jeszcze tego nie przetestowałem, ale w pewnym momencie zmienię odpowiedź.

BuvinJ
źródło
8

Zawsze umieszczam poniższy kod w pierwszych dwóch wierszach plików Pythona:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
Pereira
źródło
6

Znaleziono tutaj proste funkcje pomocnicze .

def safe_unicode(obj, *args):
    """ return the unicode representation of obj """
    try:
        return unicode(obj, *args)
    except UnicodeDecodeError:
        # obj is byte string
        ascii_text = str(obj).encode('string_escape')
        return unicode(ascii_text)

def safe_str(obj):
    """ return the byte string representation of obj """
    try:
        return str(obj)
    except UnicodeEncodeError:
        # obj is unicode
        return unicode(obj).encode('unicode_escape')
Parag Tyagi -morpheus-
źródło
Aby uzyskać uciekł bytestring (przekonwertować dowolny ciąg znaków Unicode bajtów wykorzystujących kodowanie ASCII), można użyć backslashreplaceobsł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!
jfs
Szczęśliwego Nowego Roku @JFSebastian. Po prostu denerwowałem się problemem Python-Unicode, a potem w końcu dostałem to rozwiązanie, które działało. Nie wiedziałem o tym. W każdym razie dzięki za wskazówkę.
Parag Tyagi -morpheus-
6

Po prostu dodaj do kodu zmiennej („utf-8”)

agent_contact.encode('utf-8')
Kajrat Koibagarow
źródło
4

Otwórz terminal i uruchom poniższe polecenie:

export LC_ALL="en_US.UTF-8"
Hồ Ngọc Vượng
źródło
3

Właśnie użyłem następujących:

import unicodedata
message = unicodedata.normalize("NFKD", message)

Sprawdź, co mówi o tym dokumentacja:

unicodedata.normalize (form, unistr) Zwraca normalną formę formularza dla unistr ciągu znaków Unicode. Prawidłowe wartości formularza to „NFC”, „NFKC”, „NFD” i „NFKD”.

Standard Unicode definiuje różne formy normalizacji ciągu Unicode w oparciu o definicję równoważności kanonicznej i równoważności zgodności. W Unicode kilka znaków można wyrazić na różne sposoby. Na przykład znak U + 00C7 (LATIN CAPITAL LETTER C WITH CEDILLA) można również wyrazić jako sekwencję U + 0043 (LATIN CAPITAL LETTER C) U + 0327 (COMBINING CEDILLA).

Dla każdego znaku istnieją dwie normalne formy: normalna postać C i normalna postać D. Normalna postać D (NFD) jest również znana jako rozkład kanoniczny i tłumaczy każdy znak na swoją rozkładaną formę. Normalna forma C (NFC) najpierw stosuje rozkład kanoniczny, a następnie ponownie komponuje wstępnie połączone znaki.

Oprócz tych dwóch postaci istnieją dwie dodatkowe postacie normalne oparte na równoważności zgodności. W Unicode obsługiwane są niektóre znaki, które normalnie byłyby zunifikowane z innymi znakami. Na przykład U + 2160 (ROMAN NUMERAL ONE) to tak naprawdę to samo, co U + 0049 (LITIN CAPITAL LETTER I). Jest on jednak obsługiwany w standardzie Unicode w celu zapewnienia zgodności z istniejącymi zestawami znaków (np. Gb2312).

Normalna postać KD (NFKD) zastosuje dekompozycję zgodności, tzn. Zastąpi wszystkie znaki zgodności ich odpowiednikami. Forma normalna KC (NFKC) najpierw stosuje rozkład zgodności, a następnie kompozycję kanoniczną.

Nawet jeśli dwa ciągi Unicode są znormalizowane i wyglądają tak samo dla ludzkiego czytelnika, jeśli jeden ma łączące znaki, a drugi nie, mogą nie być sobie równe.

Rozwiązuje to dla mnie. Proste i łatwe.

Przeciągnij0
źródło
3

Poniższe rozwiązanie działało dla mnie, właśnie dodane

„ciąg”

(reprezentujący ciąg jako Unicode) przed moim ciągiem.

result_html = result.to_html(col_space=1, index=False, justify={'right'})

text = u"""
<html>
<body>
<p>
Hello all, <br>
<br>
Here's weekly summary report.  Let me know if you have any questions. <br>
<br>
Data Summary <br>
<br>
<br>
{0}
</p>
<p>Thanks,</p>
<p>Data Team</p>
</body></html>
""".format(result_html)
Aravind Krishnakumar
źródło
3

Niestety działa to w Pythonie 3 przynajmniej ...

Python 3

Czasami błąd występuje w zmiennych środowiskowych i zawiera się w nich

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'))

gdzie błędy są ignorowane w kodowaniu.

hhh
źródło
2

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:

# 'value' contains the problematic data
unic = u''
unic += value
value = unic

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.

pepoluan
źródło
3
Jaka jest typewartość? przed i po tym? Myślę, że to działa, robiąc unic += valueto samo, co unic = unic + valuedodajesz ciąg znaków i Unicode, przy czym Python zakłada Unicode dla wynikowego, unictj. Bardziej precyzyjnego typu (pomyśl o tym, gdy to zrobisz a = float(1) + int(1), astaje się zmiennoprzecinkowe) i następnie value = unicwskazuje valuenowy unicobiekt, którym jest Unicode.
Tom Myddeltyn
2

Wystąpił ten błąd podczas uruchamiania manage.py migratew 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 LANGzmiennej env.

Ustawianie LANGsię en_US.UTF-8i ponownym uruchomieniu pojemnik przed ponownym uruchomieniem migracje rozwiązaniu problemu.

followben
źródło
1

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.

Simón Ramírez Amaya
źródło
tak, mój błąd dotyczył Pythona 2.7, 'a'.format (u'ñ'), a poprawnym rozwiązaniem nie jest używanie .encode ('utf-8'), ale zawsze używanie ciągów Unicode, (domyślnie w Pythonie 3 ): u'a'.format (u'ñ '),
Rogelio,
1

Staraj się unikać konwersji zmiennej na str (zmienna). Czasami może to powodować problem.

Prosta wskazówka, której należy unikać:

try: 
    data=str(data)
except:
    data = data #Don't convert to String

Powyższy przykład rozwiąże również błąd kodowania.

sam ruben
źródło
to nie działa, ponieważ po prostu napotkasz błąd w
wyjątku
0

Jeśli masz coś takiego, packet_data = "This is data"zrób to w następnym wierszu, zaraz po zainicjowaniu packet_data:

unic = u''
packet_data = unic
Nandan Kulkarni
źródło
0

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:

import sys
import codecs

def main(fIn, fOut):
    soup = BeautifulSoup(fIn)
    # Do processing, with data including non-ASCII characters
    fOut.write(unicode(soup))

if __name__ == '__main__':
    with (sys.stdin) as fIn: # Don't think we need codecs.getreader here
        with codecs.getwriter('utf-8')(sys.stdout) as fOut:
            main(fIn, fOut)
palswim
źródło
0

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.

shmakovpn
źródło
0

Zalecane rozwiązanie nie działało dla mnie i mogłem żyć z odrzucaniem wszystkich postaci nie ascii, więc

s = s.encode('ascii',errors='ignore')

co pozostawiło mi coś rozebranego, co nie powoduje błędów.

Gulzar
źródło
0

To zadziała:

 >>>print(unicodedata.normalize('NFD', re.sub("[\(\[].*?[\)\]]", "", "bats\xc3\xa0")).encode('ascii', 'ignore'))

Wynik:

>>>bats
Huzefa Usama
źródło