as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!
Jak to naprawić?
W niektórych innych statycznych aplikacjach blogowych opartych na języku Python chiński post może zostać pomyślnie opublikowany. Takich jak ta aplikacja: http://github.com/vrypan/bucket3 . Na mojej stronie http://bc3.brite.biz/ chiński post można pomyślnie opublikować.
python
python-2.7
chinese-locale
rybak
źródło
źródło
Odpowiedzi:
tl; dr / szybka poprawka
reload
hackówUnicode Zen w Python 2.x - wersja długa
Nie widząc źródła trudno jest poznać przyczynę, więc będę musiał mówić ogólnie.
UnicodeDecodeError: 'ascii' codec can't decode byte
zazwyczaj dzieje się, gdy próbujesz przekonwertować Python 2.x,str
który zawiera nie-ASCII na ciąg Unicode, bez określania kodowania oryginalnego ciągu.W skrócie, ciągi Unicode są całkowicie oddzielnym typem ciągów Python, które nie zawierają żadnego kodowania. Przechowują tylko kody punktowe Unicode i dlatego mogą przechowywać dowolny punkt Unicode z całego spektrum. Ciągi zawierają zakodowany tekst, jednak UTF-8, UTF-16, ISO-8895-1, GBK, Big5 itp. Ciągi są dekodowane do Unicode, a Unicode są kodowane do ciągów . Pliki i dane tekstowe są zawsze przesyłane w zakodowanych ciągach.
Autorzy modułu Markdown prawdopodobnie używają
unicode()
(gdzie zgłaszany jest wyjątek) jako jakościowej bramki do reszty kodu - przekonwertuje ASCII lub ponownie zawinie istniejące ciągi Unicode na nowy ciąg Unicode. Autorzy Markdown nie znają kodowania przychodzącego łańcucha, więc będą polegać na tobie, aby zdekodować łańcuchy na łańcuchy Unicode przed przekazaniem do Markdown.Ciągi znaków Unicode można zadeklarować w kodzie za pomocą
u
przedrostka ciągów znaków. Na przykładCiągi znaków Unicode mogą również pochodzić z plików, baz danych i modułów sieciowych. Kiedy tak się dzieje, nie musisz się martwić o kodowanie.
Gotchas
Konwersja z
str
na Unicode może się zdarzyć, nawet jeśli nie zadzwonisz jawnieunicode()
.Następujące scenariusze powodują
UnicodeDecodeError
wyjątki:Przykłady
Na poniższym diagramie można zobaczyć, jak słowo
café
zostało zakodowane w kodowaniu „UTF-8” lub „Cp1252” w zależności od typu terminala. W obu przykładachcaf
jest po prostu zwykłym ascii. W UTF-8é
jest kodowany przy użyciu dwóch bajtów. W „Cp1252” é ma wartość 0xE9 (która jest również wartością punktową Unicode (to nie przypadek)). Wywoływanedecode()
jest prawidłowe i konwersja na kodowanie Unicode w języku Python kończy się powodzeniem:Na tym schemacie
decode()
jest wywoływany za pomocąascii
(co jest takie samo jak wywoływanieunicode()
bez podanego kodowania). Ponieważ ASCII nie może zawierać bajtów większych niż0x7F
, spowoduje toUnicodeDecodeError
wyjątek:Kanapka Unicode
Dobrą praktyką jest tworzenie w kodzie kanapki Unicode, w której dekodujesz wszystkie przychodzące dane do ciągów Unicode, pracujesz z Unicodes, a następnie kodujesz do
str
s po wyjściu. Dzięki temu nie musisz się martwić kodowaniem ciągów znaków w środku kodu.Wejście / dekodowanie
Kod źródłowy
Jeśli chcesz upiec kod inny niż ASCII w kodzie źródłowym, po prostu utwórz ciągi Unicode, poprzedzając je ciągiem
u
. Na przykładAby umożliwić Pythonowi zdekodowanie kodu źródłowego, musisz dodać nagłówek kodowania zgodny z faktycznym kodowaniem pliku. Na przykład, jeśli plik został zakodowany jako „UTF-8”, użyłbyś:
Jest to konieczne tylko wtedy, gdy masz kod inny niż ASCII w kodzie źródłowym .
Akta
Zazwyczaj dane spoza ASCII są odbierane z pliku.
io
Moduł dostarcza TextWrapper który dekoduje plik na bieżąco, za pomocą danegoencoding
. Musisz użyć prawidłowego kodowania pliku - nie można go łatwo odgadnąć. Na przykład dla pliku UTF-8:my_unicode_string
byłby wtedy odpowiedni do przejścia do Markdown. JeśliUnicodeDecodeError
pochodzi zread()
linii, prawdopodobnie użyłeś niewłaściwej wartości kodowania.Pliki CSV
Moduł CSV Python 2.7 nie obsługuje znaków spoza ASCII 😩. Pomoc jest jednak pod ręką dzięki https://pypi.python.org/pypi/backports.csv .
Użyj go jak wyżej, ale przekaż do niego otwarty plik:
Bazy danych
Większość sterowników baz danych Python może zwracać dane w formacie Unicode, ale zwykle wymaga niewielkiej konfiguracji. Zawsze używaj ciągów Unicode do zapytań SQL.
MySQLW ciągu połączenia dodaj:
Na przykład
PostgreSQLDodaj:
HTTP
Strony internetowe można zakodować niemal w dowolnym kodowaniu.
Content-type
Nagłówek powinien zawieraćcharset
pole, aby schować w kodowaniu. Zawartość można następnie dekodować ręcznie w oparciu o tę wartość. Alternatywnie, Python-Requests zwraca Unicode wresponse.text
.Ręcznie
Jeśli musisz ręcznie dekodować ciągi, możesz po prostu zrobić
my_string.decode(encoding)
, gdzieencoding
jest odpowiednie kodowanie. Podano tutaj kodeki obsługiwane w języku Python 2.x: Standardowe kodowanie . Ponownie, jeśliUnicodeDecodeError
to zrobisz, prawdopodobnie masz złe kodowanie.Mięso Kanapki
Pracuj z Unicodes tak jak normalne napisy.
Wynik
standardowe / drukowanie
print
zapisuje przez standardowy strumień. Python próbuje skonfigurować koder na standardowym wyjściu, aby Unicode były kodowane do kodowania konsoli. Na przykład, jeśli Linux powłoki nalocale
toen_GB.UTF-8
, wyjście zostanie zakodowanyUTF-8
. W systemie Windows będziesz ograniczony do 8-bitowej strony kodowej.Niepoprawnie skonfigurowana konsola, na przykład uszkodzone ustawienia regionalne, może prowadzić do nieoczekiwanych błędów drukowania.
PYTHONIOENCODING
zmienna środowiskowa może wymusić kodowanie dla standardowego wyjścia.Akta
Podobnie jak dane wejściowe,
io.open
może służyć do przezroczystej konwersji Unicodów na zakodowane ciągi bajtów.Baza danych
Ta sama konfiguracja odczytu pozwoli na bezpośrednie pisanie Unicodów.
Python 3
Python 3 nie obsługuje bardziej Unicode niż Python 2.x, jednak jest nieco mniej zdezorientowany w tym temacie. Np. Regular
str
jest teraz ciągiem Unicode, a starystr
jest terazbytes
.Domyślne kodowanie to UTF-8, więc jeśli
.decode()
ciąg bajtów nie został podany, Python 3 używa kodowania UTF-8. Prawdopodobnie rozwiązuje to 50% problemów z Unicode.Ponadto
open()
domyślnie działa w trybie tekstowym, więc zwraca zdekodowanestr
(Unicode). Kodowanie pochodzi z ustawień regionalnych, które zwykle mają postać UTF-8 w systemach Un * x lub 8-bitową stronę kodową, taką jak Windows-1251, w polach Windows.Dlaczego nie powinieneś używać
sys.setdefaultencoding('utf8')
To paskudny hack (jest powód, dla którego musisz go użyć
reload
), który tylko maskuje problemy i utrudnia migrację do Pythona 3.x. Zrozum problem, napraw główną przyczynę i ciesz się zen z Unicode. Zobacz, dlaczego NIE powinniśmy używać sys.setdefaultencoding („utf-8”) w skrypcie py? dla dalszych szczegółówźródło
io.open
do odczytu / zapisu plików, użyjfrom __future__ import unicode_literals
, skonfiguruj inne wejścia / wyjścia danych (np. Bazy danych), aby używać Unicode.PYTHONIOENCODING=utf-8
. Jeśli to nie pomoże, musisz skontaktować się z autorem skryptu, aby naprawić jego kod.W końcu to dostałam:
Niech sprawdzę:
Powyższe pokazuje domyślne kodowanie Pythona
utf8
. Błąd już nie istnieje.źródło
str
, więc nie jest to opóźnienie. W Pythonie 2.x Unicode był w stanie przejściowym, więc byłoby niebezpiecznie założyć kodowanie podczas konwersji bajtów na Unicode. Dlatego domyślnym kodowaniem ASCII przez Py2 był celowy wybór i dlaczego zmiana domyślnego kodowania wymaga celowego włamania do ponownego ładowaniasys
. Prawidłowym sposobem na wyeliminowanie błędów kodowania w Py2 jest jednoznaczne dekodowanie i kodowanie (bajt) ciągów znaków do Unicode, gdy konwersje są konieczne - nie tylko zakładanie, że ciągi są kodowane w UTF-8.Jest to klasyczny „problem z Unicode”. Uważam, że wyjaśnienie tego jest poza zakresem odpowiedzi StackOverflow, aby całkowicie wyjaśnić, co się dzieje.
Jest to dobrze wyjaśnione tutaj .
W bardzo krótkim podsumowaniu przekazałeś coś, co jest interpretowane jako ciąg bajtów, do czegoś, co musi go zdekodować na znaki Unicode, ale domyślny kodek (ascii) zawodzi.
Prezentacja, na którą wskazałem, zawiera porady, jak tego uniknąć. Zmień swój kod w „kanapkę Unicode”. W Pythonie 2 użycie
from __future__ import unicode_literals
pomocy.Aktualizacja: jak można naprawić kod:
OK - w zmiennej „source” masz trochę bajtów. Z twojego pytania nie wynika jasno, jak się tam dostali - może czytasz je z formularza internetowego? W każdym razie nie są one kodowane za pomocą ascii, ale python próbuje przekonwertować je na Unicode, zakładając, że tak jest. Musisz wyraźnie powiedzieć, co to jest kodowanie. Oznacza to, że musisz wiedzieć, co to jest kodowanie! Nie zawsze jest to łatwe i zależy wyłącznie od tego, skąd pochodzi ten ciąg. Możesz eksperymentować z niektórymi typowymi kodowaniami - na przykład UTF-8. Podaj kodowaniu unicode () drugi parametr:
źródło
currentFile = open(filename, 'rt', encoding='latin1')
lubcurrentFile = open(filename, 'rt', encoding='utf-8')
- patrz tutaj: stackoverflow.com/a/23917799/2047442W niektórych przypadkach po sprawdzeniu domyślnego kodowania (
print sys.getdefaultencoding()
) zwraca ono, że używasz ASCII. Zmiana na UTF-8 nie działa, w zależności od zawartości zmiennej. Znalazłem inny sposób:źródło
reload(sys)
jest używany z tego konkretnego powodu.Szukałem rozwiązania następującego komunikatu o błędzie:
W końcu udało mi się to naprawić, określając „kodowanie”:
Szkoda, że to też nie pomoże.
źródło
Przyczyna tego błędu: łańcuch_wejściowy musi być Unicode, ale podano str
Przyczyna tego błędu: próba przekształcenia łańcucha wejściowego Unicode na Unicode
Najpierw sprawdź, czy łańcuch wejściowy jest,
str
i w razie potrzeby przekonwertuj go na Unicode:Po drugie, powyższe po prostu zmienia typ, ale nie usuwa znaków innych niż ascii. Jeśli chcesz usunąć znaki inne niż ascii:
źródło
Uważam, że najlepiej jest zawsze konwertować na Unicode - ale jest to trudne do osiągnięcia, ponieważ w praktyce będziesz musiał sprawdzić i przekonwertować każdy argument na każdą pisaną funkcję i metodę, która obejmuje pewną formę przetwarzania łańcucha.
Wymyśliłem więc następujące podejście, aby albo gwarantować Unicode, albo ciągi bajtów, z obu danych wejściowych. Krótko mówiąc, dołącz i użyj następujących lambdas:
Przykłady:
Oto kilka argumentów na ten temat .
źródło
print unicode(u'Zürich', encoding="UTF-8")
a potem narzekają: „O dziwo, nie można zakodować rozszerzenia Unicode w UTF8”.unicode()
nie koduje; dekoduje i nie można dekodować Unicode - już jest dekodowany!Aby rozwiązać ten problem na poziomie systemu operacyjnego w instalacji Ubuntu, sprawdź następujące elementy:
Jeśli dostaniesz
zamiast
następnie ustaw
LC_CTYPE
iLC_ALL
tak:źródło
Kodowanie przekształca obiekt Unicode w obiekt łańcuchowy. Myślę, że próbujesz zakodować obiekt łańcuchowy. najpierw przekonwertuj swój wynik na obiekt Unicode, a następnie zakoduj ten obiekt Unicode na „utf-8”. na przykład
źródło
Miałem ten sam problem, ale nie działał w Pythonie 3. Postępowałem zgodnie z tym i rozwiązałem mój problem:
Musisz ustawić kodowanie podczas odczytywania / zapisywania pliku.
źródło
Wystąpił ten sam błąd i to rozwiązało mój błąd. Dzięki! Python 2 i Python 3 różniące się obsługą Unicode powodują, że marynowane pliki są dość niekompatybilne z ładowaniem. Więc użyj argumentu kodującego marynaty pytona. Poniższy link pomógł mi rozwiązać podobny problem, gdy próbowałem otworzyć marynowane dane z mojego pytona 3.7, podczas gdy mój plik został pierwotnie zapisany w wersji python 2.x. https://blog.modest-destiny.com/posts/python-2-and-3-compatible-pickle-save-and-load/ Kopiuję funkcję load_pickle w moim skrypcie i podczas ładowania mojego wywołałem load_pickle (plik pickle_file) dane wejściowe takie jak to:
Funkcja load_pickle jest tutaj:
źródło
load_pickle
funkcji do swojej odpowiedzi.To działało dla mnie:
źródło
Krótko mówiąc, aby zapewnić poprawną obsługę Unicode w Pythonie 2:
io.open
do odczytu / zapisu plikówfrom __future__ import unicode_literals
print(text.encode('ascii', 'replace').decode())
Wyjaśnienia znajdują się w szczegółowej odpowiedzi @Alastair McCormack .
źródło
io.open(path, 'r', encoding='utf-8')
do odczytu plików zakodowanych w utf-8.Miałem ten sam błąd, w przypadku adresów URL zawierających znaki inne niż ascii (bajty o wartości> 128) moje rozwiązanie:
Uwaga: utf-8, utf8 to po prostu aliasy. Używanie tylko „utf8” lub „utf-8” powinno działać w ten sam sposób
W moim przypadku, pracował dla mnie, w Pythonie 2.7, przypuszczam, że to przypisanie zmieniło „coś” w
str
wewnętrznej reprezentacji - tj. Wymusza prawidłowe dekodowanie sekwencji bajtów kopii zapasowejurl
i ostatecznie wstawia ciąg do utf-8str
z cała magia we właściwym miejscu. Unicode w Pythonie to dla mnie czarna magia. Mam nadzieję, że przydatneźródło
Mam ten sam problem z ciągiem „PastelerÃa Mallorca” i rozwiązałem:
źródło
W projekcie Django (1.9.10) / Python 2.7.5 mam częste
`UnicodeDecodeError
wyjątki; głównie gdy próbuję podać ciągi znaków Unicode do logowania. Stworzyłem funkcję pomocniczą dla dowolnych obiektów, która zasadniczo formatuje 8-bitowe ciągi ascii i zamienia wszelkie znaki spoza tabeli na „?”. Myślę, że nie jest to najlepsze rozwiązanie, ale ponieważ domyślnym kodowaniem jest ascii (i nie chcę go zmieniać), zrobi to:źródło
Ten błąd występuje, gdy w naszym ciągu znajduje się kilka znaków spoza ASCII i wykonujemy dowolne operacje na tym ciągu bez odpowiedniego dekodowania. To pomogło mi rozwiązać mój problem. Czytam plik CSV z identyfikatorem kolumn, tekstem i znakami dekodującymi, jak poniżej:
źródło
Oto moje rozwiązanie, po prostu dodaj kodowanie.
with open(file, encoding='utf8') as f
A ponieważ odczytanie pliku rękawicy zajmie dużo czasu, polecam plik rękawicy do pliku numpy. Gdy czas Netx odczytasz wagi osadzania, zaoszczędzi ci to czasu.
Link Gist: https://gist.github.com/BrambleXu/634a844cdd3cd04bb2e3ba3c83aef227
źródło
Podaj: # encoding = utf-8 u góry pliku Python, powinno to rozwiązać problem
źródło