UnicodeDecodeError: kodek „ascii” nie może zdekodować bajtu 0xef na pozycji 1


106

Mam kilka problemów, próbując zakodować ciąg do UTF-8. Próbowałem wielu rzeczy, w tym używania string.encode('utf-8')i unicode(string), ale pojawia się błąd:

UnicodeDecodeError: kodek „ascii” nie może zdekodować bajtu 0xef na pozycji 1: numer porządkowy poza zakresem (128)

To jest mój ciąg:

(。・ω・。)ノ

Nie rozumiem, co się dzieje, jakiś pomysł?

Edycja: Problem polega na tym, że drukowanie ciągu w takiej postaci, w jakiej jest, nie jest wyświetlane poprawnie. Również ten błąd, gdy próbuję go przekonwertować:

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: ordinal not in range(128)

To po prostu normalnie wstawiony ciąg. To samo dzieje się, gdy próbuję go wydrukować.
Markum

Spotykam się z tym samym, gdy instaluję pip i naprawiam to tutaj: [zainstaluj jakiś program] [1] [1]: stackoverflow.com/questions/17931726/ ...
BollMose

Odpowiedzi:


70

Ma to związek z tym, że kodowanie twojego terminala nie jest ustawione na UTF-8. Oto mój terminal

$ echo $LANG
en_GB.UTF-8
$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
(。・ω・。)ノ
>>> 

Na moim terminalu przykład działa z powyższym, ale jeśli pozbędę się tego LANGustawienia, to nie zadziała

$ unset LANG
$ python
Python 2.7.3 (default, Apr 20 2012, 22:39:59) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-5: ordinal not in range(128)
>>> 

Zapoznaj się z dokumentacją dotyczącą wersji systemu Linux, aby dowiedzieć się, jak wprowadzić tę zmianę na stałe.


1
Przyczyną mogą być również brakujące lokalizacje. Aby je zainstalować, uruchom sudo apt-get install language-pack-delub sudo locale-gen de_DE.UTF-8(dla języków niemieckich).
Nie

Dla mnie brakującą zmienną środowiskową jest LC_ALL, a najprostszą wartością, która by to naprawić, jestC.UTF-8
Robin Winslow

24

próbować:

string.decode('utf-8')  # or:
unicode(string, 'utf-8')

edytować:

'(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'.decode('utf-8')daje u'(\uff61\uff65\u03c9\uff65\uff61)\uff89', co jest poprawne.

więc twój problem musi być w innym miejscu, być może jeśli spróbujesz coś z nim zrobić, gdy zachodzi niejawna konwersja (może to być drukowanie, zapisywanie do strumienia ...)

aby powiedzieć więcej, musimy zobaczyć kod.


Obaj wracająUnicodeEncodeError: 'charmap' codec can't encode characters in position 1-5: character maps to <undefined>
Markum

'(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
Markum

1
Wszystko, co próbuję zrobić, to wydrukować oryginalny ciąg w oryginalnym formacie, ale otrzymuję (´¢í´¢Ñ¤ë´¢Ñ´¢í)´¥ë.
Markum

4
stringjest utf8 kodowane. jeśli go wydrukujesz, po prostu zapisuje bajty do strumienia wyjściowego, a jeśli twój terminal nie zinterpretuje go jako utf8, skończysz ze śmieciami. z decodeprzekonwertować go na Unicode, a następnie można encodego ponownie do kodowania terminal rozumie.
mata

21

Moje +1 do komentarza maty na https://stackoverflow.com/a/10561979/1346705 oraz do demonstracji Nicka Craiga-Wooda. Odszyfrowałeś poprawnie ciąg. Problem polega na tym, że printpolecenie konwertuje ciąg Unicode na kodowanie konsoli, a konsola nie jest w stanie wyświetlić ciągu. Spróbuj zapisać ciąg do pliku i spójrz na wynik za pomocą przyzwoitego edytora obsługującego Unicode:

import codecs

s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
s1 = s.decode('utf-8')
f = codecs.open('out.txt', 'w', encoding='utf-8')
f.write(s1)
f.close()

Wtedy zobaczysz (。・ω・。)ノ.


10

Jeśli pracujesz na zdalnym hoście, spójrz /etc/ssh/ssh_configna swój lokalny komputer.

Gdy ten plik zawiera wiersz:

SendEnv LANG LC_*

skomentuj to, dodając #na początku wiersza. To może pomóc.

Za pomocą tej linii sshwysyła zmienne środowiskowe związane z językiem komputera do zdalnego hosta. Powoduje wiele problemów.


Dzięki! Te rozwiązały problem, który miałem instalując pakiety pip z ansible i vagrant
Maritza Esparza


5

Możesz użyć poniższego kodu w górnej części skryptu, jak zasugerował Andrei Krasutski .

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

Ale proponuję również dodanie # -*- coding: utf-8 -*linii na samej górze skryptu.

Pominięcie tego powoduje wyświetlenie poniższego błędu w moim przypadku, gdy próbuję wykonać basic.py.

$ python basic.py
  File "01_basic.py", line 14
SyntaxError: Non-ASCII character '\xd9' in file basic.py on line 14, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Poniżej znajduje się kod, w basic.pyktórym wyrzuca powyższy błąd.

kod z błędem

from pylatex import Document, Section, Subsection, Command, Package
from pylatex.utils import italic, NoEscape

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

def fill_document(doc):
    with doc.create(Section('ِش سثؤفهخى')):
        doc.append('إخع ساخعمي شمصشغس سحثشن فاث فقعفا')
        doc.append(italic('فشمهؤ ؤخىفثىفس شقث شمسخ ىهؤث'))

        with doc.create(Subsection('آثص ٍعلاسثؤفهخى')):
            doc.append('بشةخعس ؤقشئغ ؤاشقشؤفثقس: $&#{}')


if __name__ == '__main__':
    # Basic document
    doc = Document('basic')
    fill_document(doc)

Następnie dodałem # -*- coding: utf-8 -*-linię na samej górze i wykonałem . Zadziałało.

kod bez błędu

# -*- coding: utf-8 -*-
from pylatex import Document, Section, Subsection, Command, Package
from pylatex.utils import italic, NoEscape

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

def fill_document(doc):
    with doc.create(Section('ِش سثؤفهخى')):
        doc.append('إخع ساخعمي شمصشغس سحثشن فاث فقعفا')
        doc.append(italic('فشمهؤ ؤخىفثىفس شقث شمسخ ىهؤث'))

        with doc.create(Subsection('آثص ٍعلاسثؤفهخى')):
            doc.append('بشةخعس ؤقشئغ ؤاشقشؤفثقس: $&#{}')


if __name__ == '__main__':
    # Basic document
    doc = Document('basic')
    fill_document(doc)

Dzięki.


1
Używanie #coding: utf-8zamiast # -*- coding: utf-8 -*- tego jest łatwiejsze do zapamiętania. Działa po wyjęciu z pudełka z Python PEP 263 - Definiowanie kodowania kodu źródłowego w języku Python .
Andrei Krasutski

Dzieki za sugestie. Spróbuję na moim końcu i zaktualizuję to w odpowiedzi.
hygull

4

Żadnych problemów z moim terminalem. Powyższe odpowiedzi pomogły mi spojrzeć we właściwych kierunkach, ale nie zadziałały, dopóki nie dodałem 'ignore':

fix_encoding = lambda s: s.decode('utf8', 'ignore')

Jak wskazano w poniższym komentarzu, może to prowadzić do niepożądanych rezultatów. OTOH może też po prostu wykonać tę sztuczkę wystarczająco dobrze, aby wszystko działało i nie przejmujesz się utratą niektórych postaci.


2
To jest złe, wymuszasz kodowanie funkcji lambda, aby ignorowała samo kodowanie, co oznacza, że ​​tracisz znaki.
Maximiliano Rios

2
To rozwiązało mój problem, w którym nie znałem oryginalnego kodowania i nie przejmowałem się utratą niektórych znaków.
Edhowler,

2

to działa dla ubuntu 15.10:

sudo locale-gen "en_US.UTF-8"
sudo dpkg-reconfigure locales

1

Wygląda na to, że Twój ciąg jest zakodowany utf-8, więc na czym dokładnie polega problem? Albo co próbujesz tutaj zrobić ..?

Python 2.7.3 (default, Apr 20 2012, 22:39:59) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '(\xef\xbd\xa1\xef\xbd\xa5\xcf\x89\xef\xbd\xa5\xef\xbd\xa1)\xef\xbe\x89'
>>> s1 = s.decode('utf-8')
>>> print s1
(。・ω・。)ノ
>>> s2 = u'(。・ω・。)ノ'
>>> s2 == s1
True
>>> s2
u'(\uff61\uff65\u03c9\uff65\uff61)\uff89'

Drukowanie oryginalnego ciągu, jaki jest podany (´¢í´¢Ñ¤ë´¢Ñ´¢í)´¥ë, chcę, aby był poprawnie zakodowany.
Markum

1

W moim przypadku było to spowodowane zapisywaniem mojego pliku Unicode z "BOM". Aby rozwiązać ten problem, otworzyłem plik używając BBEdit i zrobiłem "Zapisz jako ..." wybierając do kodowania "Unicode (UTF-8)", a nie to, z czym przyszedł, czyli "Unicode (UTF-8, z BOM) "


0

Otrzymałem ten sam typ błędu i stwierdziłem, że konsola nie jest w stanie wyświetlić ciągu w innym języku. Dlatego dokonałem poniższych zmian w kodzie, aby ustawić default_charset jako UTF-8.

data_head = [('\x81\xa1\x8fo\x89\xef\x82\xa2\x95\xdb\x8f\xd8\x90\xa7\x93x\x81\xcb3\x8c\x8e\x8cp\x91\xb1\x92\x86(\x81\x86\x81\xde\x81\x85)\x81\xa1\x8f\x89\x89\xf1\x88\xc8\x8aO\x81A\x82\xa8\x8b\xe0\x82\xcc\x90S\x94z\x82\xcd\x88\xea\x90\xd8\x95s\x97v\x81\xa1\x83}\x83b\x83v\x82\xcc\x82\xa8\x8e\x8e\x82\xb5\x95\xdb\x8c\xaf\x82\xc5\x8fo\x89\xef\x82\xa2\x8am\x92\xe8\x81\xa1', 'shift_jis')]
default_charset = 'UTF-8' #can also try 'ascii' or other unicode type
print ''.join([ unicode(lin[0], lin[1] or default_charset) for lin in data_head ])


-1

BOM, tak często jest dla mnie BOM

vi plik, użyj

:set nobomb

i zapisz to. To prawie zawsze rozwiązuje problem w moim przypadku


-1

Miałem ten sam błąd, z adresami URL zawierającymi znaki inne niż ASCII (bajty o wartościach> 128)

url = url.decode('utf8').encode('utf-8')

Pracowałem dla mnie, w Pythonie 2.7, przypuszczam, że to przypisanie zmieniło `` coś '' w strwewnętrznej reprezentacji - tj. Wymusza prawidłowe dekodowanie sekwencji bajtów z zabezpieczeniem urli ostatecznie umieszcza łańcuch w utf-8 str z całą magią w dobre miejsce. Unicode w Pythonie to dla mnie czarna magia. Mam nadzieję, że przydatne


-2

rozwiązuję ten problem zmieniając w pliku settings.py 'ENGINE': 'django.db.backends.mysql', nie używam 'ENGINE': 'mysql.connector.django',


@rayryeng Czy możesz wyjaśnić powód swojej zmiany? Wydaje się, że całkowicie zmienia to znaczenie tego, co napisał PO, od rekomendowania określonego ustawienia do zalecania przeciwko niemu.
nikt

@AndrewMedico - Moje przeprosiny. Widziałem, że ten post był bardzo podobny do innego, więc pomyślałem, że są takie same. Wrócę.
rayryeng

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.