Mam skrypt Pythona i ostatnio zauważyłem, że na niektórych danych wejściowych pojawiały się błędy kodowania. Zauważyłem, że "inteligentne cytaty" powodują problemy. Chciałbym poznać radę, jak to przezwyciężyć. Używam Python 2, więc muszę powiedzieć mojemu skryptowi, że chcę zakodować wszystko w UTF-8.


Myślałem, że to wystarczy:

mystring.encode("utf-8")

I w dużej mierze zadziałało, dopóki nie natknąłem się na sprytne cytaty (i prawdopodobnie jest wiele innych rzeczy, które będą powodować problemy, dlatego publikuję tutaj). Na przykład:

mystring = "hi"
mystring.encode("utf-8")

Wyjście jest

'hi'

Ale za to:

mystring2 = "’"
mystring.encode("utf-8")

Wyjście jest

UnicodeDecodeError
  Traceback (most recent call last)
    <ipython-input-21-f563327dcd27> in <module>()
    ----> 1 mystring.encode("utf-8")
  UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in
  position 0: ordinal not in range(128)

Stworzyłem funkcję do obsługi danych wejściowych JSON, które otrzymuję (czasami otrzymuję wartości null/None, a czasem wartości liczbowe, chociaż głównie unicode, dlatego mam kilka instrukcji if):

def xstr(s):
    if s is None:
        return ''
    if isinstance(s, basestring):
        return str(s.encode("utf-8"))
    else:
        return str(s)

To zadziałało całkiem dobrze (do czasu tego problemu z inteligentnymi cytatami)

Mam dwa pytania:

  1. Dlaczego nie można zakodować „inteligentnych cytatów” w UTF-8 i czy istnieją inne ograniczenia UTF-8, czy też całkowicie błędnie interpretuję to, co widzę?

  2. Czy podejście, które zastosowałem (tj. użycie mojej funkcji niestandardowej) jest najlepszym sposobem na poradzenie sobie z tym? Próbowałem użyć try/except, aby złapać przypadki inteligentnych cytatów, ale to nie zadziałało.

0
Calamari 2 listopad 2018, 12:56

1 odpowiedź

Najlepsza odpowiedź

Python nie może zakodować ciągu, ponieważ nie zna jego bieżącego kodowania. Będziesz musiał użyć u"’" w Pythonie 2, aby powiedzieć Pythonowi, że jest to ciąg Unicode. ("\xe2" jest pierwszym bajtem kodowania UTF-8 tego znaku, ale Python nie wie, że jest w UTF-8, ponieważ tego nie powiedziałeś. Możesz umieścić -*- coding: utf-8 -*- komentarz u góry pliku lub jednoznacznie zaprezentuj znak jako u"\u2219".)

Podobnie, aby przekonwertować ciąg odczytany z dysku, musisz przekonwertować go na Unicode, dzięki czemu można go następnie zakodować jako UTF-8.

print(s.decode('iso-8859-1').encode('utf-8'))

Tutaj oczywiście 'iso-8859-1' jest tylko przypadkowym przypuszczeniem. Musisz znać kodowanie, w przeciwnym razie możesz otrzymać niepoprawne dane wyjściowe.

0
tripleee 2 listopad 2018, 13:29