2010-05-06 16 views
11

Poniższy ciąg Unicode i może występować na własną rękę, jeśli zdefiniowane jednoznacznie:Jak przekonwertować kod Unicode na ciąg znaków na poziomie Python?

>>> value_str='Andr\xc3\xa9' 
>>> value_uni=u'Andr\xc3\xa9' 

Jeśli mam u'Andr\xc3\xa9' przypisany tylko do zmiennej jak wyżej, w jaki sposób mogę przekonwertować go do 'Andr\xc3\xa9' w Pythonie 2.5 lub 2.6?

EDIT:

Zrobiłem następujące:

>>> value_uni.encode('latin-1') 
'Andr\xc3\xa9' 

który rozwiązuje mój problem. Czy ktoś może mi wyjaśnić, co dokładnie się dzieje?

+0

To jest TRZECIE pytanie, o które prosiłeś w mniej niż jeden dzień, a wszystko opiera się na tym samym nieporozumieniu. 'u'Andr \ xc3 \ xa9'' jest nonsensem uzyskanym przez podwójne kodowanie z utf8 i latin1. Tylko tego nie rób! –

+0

To właśnie mnie zastanawia. Jak to się stało, od oryginalnego akcentu do tego, czym jest teraz? Kiedy mówisz o podwójnym kodowaniu z utf8 i latin1, czy jest to w sumie 3 kodowanie (2 utf8 + 1 latin1)? Jaka jest kolejność kodowania od stanu pierwotnego do bieżącego? –

Odpowiedz

11

Wydaje się zdobyć twoje kodowanie pomieszania się. Wydaje się prawdopodobne, że to, czego naprawdę chcesz, to u'Andr\xe9', co jest równoważne z 'André'.

Ale wydaje się, że kodowanie UTF-8 zostało nieprawidłowo zdekodowane. Możesz to naprawić, konwertując ciąg znaków Unicode na zwykły ciąg znaków. Nie jestem pewien, co jest najlepszym sposobem, ale to wydaje się działać:

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9') 
'Andr\xc3\xa9' 

Następnie dekoduje go poprawnie:

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9').decode('utf8') 
u'Andr\xe9'  

Teraz jest w odpowiednim formacie.

Zamiast tego jednak, jeśli to możliwe, powinieneś spróbować ustalić, dlaczego dane zostały błędnie zakodowane, i rozwiązać ten problem.

-1

Wydaje się

str(value_uni) 

powinno działać ... przynajmniej wtedy gdy próbowałem go.

EDIT: Okazuje się, że działa to tylko dlatego, że domyślne kodowanie mojego systemu jest, o ile wiem, ISO-8859-1 (Latin-1). Tak dla niezależny od platformy wersja tego, spróbuj

value_uni.encode('latin1') 
+0

Próbowałem, ale otrzymuję UnicodeEncodeError: kodek 'ascii' nie może kodować znaków w pozycji 4-5: porządkowa nie w zakresie (128).Którą wersję Pythona używasz i na jakim systemie operacyjnym? –

+0

Python 2.6.4 na Linuksie ... chociaż teraz o tym myślę, możliwe jest, że domyślne kodowanie mojego systemu jest ustawione inaczej niż twoje. Nie jestem do końca pewien, jakie jest moje domyślne kodowanie. –

+0

OK, rozumiem, wypróbuj nową metodę. –

3

value_uni.encode('utf8') lub cokolwiek kodowanie trzeba.

Zobacz http://docs.python.org/library/stdtypes.html#str.encode

+1

Po prostu dodać. Powyższe może wydawać się takie samo, ale literał Unicode składa się z punktów kodu, które odpowiadają symbolom, a ciąg normalny jest bez znaczenia, chyba że znasz kodowanie. – dhill

+0

Otrzymuję "Andr \ xc3 \ x83 \ xc2 \ xa9", czy to nie różni się od "Andr \ xc3 \ xa9"? –

+0

@Thierry: Otrzymasz to, jeśli zepsujesz i umieścisz UTF-8 w unicode. –

0

uproszczone wyjaśnienie. Typ str jest w stanie pomieścić tylko znaki z zakresu 0-255. Jeśli chcesz przechowywać Unicode (który może zawierać znaki z dużo szerszego zakresu), musisz najpierw kodować Unicode do formatu odpowiedniego dla str, na przykład UTF-8.

Aby wykonać tę metodę wywołania, należy ją zakodować na obiekcie str, a jako argument podać pożądane kodowanie, na przykład this_is_str = value_uni.encode('utf-8').

Możesz przeczytać dłuższy i bardziej dogłębny (i agnostyczny język) artykuł na temat obsługi Unicode tutaj: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).

Kolejny doskonały artykuł (tym razem Python specyficzne): Unicode HOWTO

1

OP nie konwertuje do ascii ani utf-8. Dlatego sugerowane metody encode nie będą działać. Spróbuj tego:

v = u'Andr\xc3\xa9' 
s = ''.join(map(lambda x: chr(ord(x)),v)) 

chr(ord(x)) firma pobiera wartość liczbową znaku Unicode (który lepiej pasuje w jeden bajt dla danej aplikacji), a połączenie ''.join to idiom, który przekształca listę wskazówki z powrotem do zwykłego strunowy. Bez wątpienia istnieje bardziej elegancki sposób.

1

Jeśli masz u'Andr\xc3\xa9', prawdopodobnie oryginalnie UTF-8 pochodziło z dowolnego źródła, z którego zostało pozyskane. Jeśli to możliwe, należy ponownie odczytać źródło, dekodując za pomocą "utf-8". W przeciwnym razie po prostu odwrócić błąd.

>>> print u'Andr\xc3\xa9'.encode('latin-1').decode('utf-8') 
André 
5

Pytałeś (w komentarzu) „” "To, co mnie zastanawiające Jak poszło z niego oryginalny akcentowany do tego, co jest teraz Kiedy mówisz podwójne kodowanie z UTF-8? i latin1, czy to w sumie 3 kodowania (2 utf8 + 1 latin1)? Jaka jest kolejność kodowania od stanu pierwotnego do bieżącego? "" "

W odpowiedzi Marka Byersa, mówi: "" wydaje się, że kodowanie UTF-8 zostało niepoprawnie zdekodowane "" ". Przyjąłeś odpowiedź. Ale nadal jesteś zdziwiony? OK, oto opis ciosu:

Uwaga: Wszystkie ciągi będą wyświetlane przy użyciu (domyślnie) repr(). unicodedata.name() zostanie użyty do sprawdzenia zawartości. W ten sposób warianty kodowania konsoli nie mogą mylić interpretacji napisów.

Stan początkowy: masz obiekt Unicode o nazwie u1. Zawiera e-ostra:

>>> u1 = u'\xe9' 
>>> import unicodedata as ucd 
>>> ucd.name(u1) 
'LATIN SMALL LETTER E WITH ACUTE' 

można zakodować U1 jako UTF-8 i S nazwać wynik:

>>> s = u1.encode('utf8') 
>>> s 
'\xc3\xa9' 

dekodowania s przy użyciu latin1 - NIEWŁAŚCIWIE; s zostało zakodowane za pomocą utf8, NOT latin1. Rezultatem są bezsensowne śmieci.

>>> u2 = s.decode('latin1') 
>>> u2 
u'\xc3\xa9' 
>>> ucd.name(u2[0]); ucd.name(u2[1]) 
'LATIN CAPITAL LETTER A WITH TILDE' 
'COPYRIGHT SIGN' 
>>> 

Proszę zrozumieć: unicode_object.encode('x').decode('y) gdy x = y jest zwykle [patrz uwaga poniżej] nonsens; podniosą wyjątek, jeśli będziesz miał szczęście; jeśli masz pecha, będzie to cicho tworzyć bełkot. Należy również zrozumieć, że tworzenie cichego bełkotu nie jest błędem - nie ma żadnego ogólnego sposobu, w jaki Python (lub jakikolwiek inny język) mógłby wykryć, że popełniono bzdury. Dotyczy to w szczególności sytuacji, w której występuje łacińska1, ponieważ wszystkie 256 punktów współrzędnych mapuje 1 na 1 z pierwszymi 256 punktami kodowymi Unicode, więc niemożliwe jest uzyskanie UnicodeDecodeError z str_object.decode ("latin1").

Oczywiście, nienormalnie (ma się nadzieję, że jest nienormalny), być może trzeba cofnąć takie bzdury, wykonując gibberish_unicode_object.encode('y').decode('x'), jak sugerowano w różnych odpowiedziach na twoje pytanie.

Powiązane problemy