2013-10-22 14 views
13

jestem w stanie konwertować następujący Unicode do ASCII bez utraty danych:Python - Unicode do konwersji ASCII

u'ABRA\xc3O JOS\xc9' 

Próbowałem encode i decode i nie będzie to zrobić.

Czy ktoś ma sugestię?

+0

Czy rzeczywiście trzeba kodować do ASCII lub po prostu "jakiś zestaw znaków 8-bitowych" lub "domyślny zestaw znaków 8-bitowej mojej platformy" lub coś w tym stylu? – abarnert

+0

To było do ASCII. Połączenie z bazą danych zostało ustawione jako ASCII. –

+1

Dla odniesienia, ciąg w Unicode wygląda jak _ABRAÃO JOSÉ_ – nealmcb

Odpowiedz

37

Znaki Unicode u'\xce0' i u'\xc9' nie mają żadnych odpowiadających wartości ASCII. Tak więc, jeśli nie chcesz tracić danych, musisz zakodować te dane w pewien sposób, który jest ważny jako ASCII. Dostępne są następujące opcje:

>>> print s.encode('ascii', errors='backslashreplace') 
ABRA\xc3O JOS\xc9 
>>> print s.encode('ascii', errors='xmlcharrefreplace') 
ABRAÃO JOSÉ 
>>> print s.encode('unicode-escape') 
ABRA\xc3O JOS\xc9 
>>> print s.encode('punycode') 
ABRAO JOS-jta5e 

Wszystkie te ciągi ASCII, i zawierać wszystkie informacje z oryginalnego ciąg Unicode (a więc wszystkie one mogą zostać odwrócone bez utraty danych), ale żaden z nich nie są takie całkiem za użytkownika końcowego (i żaden z nich nie może być odwrócony tylko przez decode('ascii')).

Aby uzyskać więcej informacji, zobacz str.encode, Python Specific Encodings i Unicode HOWTO.


Na marginesie, gdy niektórzy mówią „ASCII”, ale naprawdę nie mam na myśli „ASCII”, ale raczej „każdy 8-bitowy zestaw znaków, który jest rozszerzeniem ASCII” lub „niektóre szczególności 8- zestaw znaków bitowych, który mam na myśli ". Jeśli o to ci chodziło, rozwiązaniem jest, aby zakodować na prawą 8-bitowym zestawem znaków:

>>> s.encode('utf-8') 
'ABRA\xc3\x83O JOS\xc3\x89' 
>>> s.encode('cp1252') 
'ABRA\xc3O JOS\xc9' 
>>> s.encode('iso-8859-15') 
'ABRA\xc3O JOS\xc9' 

Najtrudniejsze jest wiedzieć, który zestaw znaków chodziło. Jeśli piszesz zarówno kod, który tworzy 8-bitowe łańcuchy, jak i kod je zużywający, a nie wiesz nic lepszego, masz na myśli UTF-8. Jeśli kod zużywający ciągi 8-bitowe to, powiedzmy, funkcja open lub przeglądarka internetowa, do której podajesz stronę lub coś innego, rzeczy są bardziej skomplikowane i nie ma łatwej odpowiedzi bez znacznie większej ilości informacji.

+0

Niesamowita odpowiedź. –

+0

Dzięki. To pomogło. Zrobiłem już xmlcharrefreplace, ale kiedy pisałem do Oracle DB, wstawiłem śmieci do mojego ciągu. Rozwiązałem problem zmieniając parametr NLS_LANG. 'os.environ [" NLS_LANG "] =" AMERICAN_AMERICA.WE8ISO8859P1 "', a następnie konwertowanie na "latin-1" –

+0

@AdrianoAlmeida: Zwróć uwagę, że chociaż Latin-1/ISO-8859-1 obsługuje oba dotychczasowe znaki, nie obsługuje większości Unicode. Tak więc, jak tylko ktoś spróbuje podać ci rosyjskie lub chińskie imię, otrzymasz "UnicodeError". Jeśli możesz ustawić w Oracle opcję używania UTF-8, unikniesz takich problemów w przyszłości. Jeśli nie możesz ... po prostu miej to na uwadze i odpowiednio zaprojektuj swoje testy. – abarnert