Google App Engine używa Python 2.5.2, najwyraźniej z włączoną obsługą UCS4. Ale magazyn danych GAE używa wewnętrznie UTF-8. Więc jeśli przechowujesz u \ ud834 \ udd0c (długość 2) w magazynie danych, po pobraniu go otrzymasz "\ U0001d10c" (długość 1). Próbuję policzyć liczbę znaków unicode w ciągu znaków w sposób, który daje taki sam wynik przed i po przechowywaniu go. Próbuję więc znormalizować ciąg znaków (z u '\ ud834 \ udd0c' do '\ U0001d10c'), jak tylko go otrzymam, przed obliczeniem jego długości i umieszczeniem w magazynie danych. Wiem, że mogę po prostu zakodować go na UTF-8, a następnie ponownie dekodować, ale czy istnieje bardziej prosty/skuteczny sposób?Jak uzyskać wiarygodną liczbę znaków Unicode w Pythonie?
Odpowiedz
wiem, że mogę po prostu zakodować go na UTF-8, a następnie dekodować ponownie
Tak, to zwykle idiom, aby naprawić problem, gdy masz „UTF-16 surogatów w UCS-4 ciąg "input. Ale jak powiedział mechaniczny ślimak, ten sygnał wejściowy jest zniekształcony i powinieneś naprawiać wszystko, co jest produkowane w jego preferencjach.
Czy istnieje bardziej prosty/skuteczny sposób?
Cóż ... mógłby zrobić to ręcznie z regex, jak:
re.sub(
u'([\uD800-\uDBFF])([\uDC00-\uDFFF])',
lambda m: unichr((ord(m.group(1))-0xD800<<10)+ord(m.group(2))-0xDC00+0x10000),
s
)
nie prościej
pewno ... Ja też mam wątpliwości co do tego, czy to jest rzeczywiście bardziej skuteczne!
Dzięki. Moje dane wejściowe pochodzą ze strumienia yaml, który zawierał zastępcze jednostki kodowe, a ustalenie, że strumień nie zawiera surogatów, zdaje się uniemożliwiać ich wyświetlenie w unicode. Tak więc przyjrzę się naprawieniu strumienia. – Travis
Jakie kodowanie jest YAML? Jeśli jest to kodowanie UTF-16, te znaki zastępcze * powinny * być konwertowane na pojedyncze znaki Unicode ... jeśli jednak jest to UTF-8, to producent popełnił błąd. (UTF-8-z-surogatami jest znany jako "CESU-8" i nie powinien być używany.) – bobince
Jestem prawie pewien, że regex nie będzie bardziej wydajny. –
Niestety, zachowanie interpretera CPython w wersjach starszych niż 3.3 zależy od tego, czy jest zbudowany z "wąskim" lub "szerokim" wsparciem dla Unicode. Tak więc ten sam kod, na przykład wywołanie len
, może mieć inny wynik w różnych wersjach standardowego interpretera. Zobacz przykłady this question.
Rozróżnienie między "wąskim" a "szerokim" polega na tym, że "wąscy" tłumacze wewnętrznie przechowują 16-bitowe jednostki kodowe (UCS-2), podczas gdy "szerokie" interpretery wewnętrznie przechowują 32-bitowe jednostki kodowe (UCS-4) . Kod punkty U + 10000 i powyżej (poza płaszczyzną podstawową-wielojęzyczna) mają len
dwóch na „wąskie” tłumaczy, ponieważ potrzebne są dwa UCS-2 Kod szt je (za pomocą surogatów) reprezentują, i to, co len
środki. W "szerokich" kompilacjach potrzebny jest tylko jeden kod UCS-4 jednostka dla kodu innego niż BMP punkt, więc dla tych kompilacji len
jest jeden dla takich punktów kodowych.
Potwierdziłem, że poniżej obsługuje wszystkie ciągi znaków unicode
niezależnie od tego, czy zawierają pary zastępcze, i działa w CPython 2.7 zarówno w wąskich, jak i szerokich kompilacjach. (Możliwe, że określenie ciągu znaków, takiego jak u'\ud83d\udc4d'
, w szerokim tłumaczeniu odzwierciedla twierdzące pragnienie przedstawienia kompletnego zastępczego kodu punkt w odróżnieniu od jednostki o kodach częściowych i dlatego nie jest automatycznie błędem do korekty, ale ja '. m ignorując że tutaj. jest to przypadek kant i zwykle nie jest pożądana przypadku użycia).
@invoke
, stosowana poniżej sposób, aby uniknąć powtarzania obliczeń bez dodając do modułu __dict__
.
invoke = lambda f: f() # trick taken from AJAX frameworks
@invoke
def codepoint_count():
testlength = len(u'\U00010000') # pre-compute once
assert (testlength == 1) or (testlength == 2)
if testlength == 1:
def closure(data): # count function for "wide" interpreter
u'returns the number of Unicode code points in a unicode string'
return len(data.encode('UTF-16BE').decode('UTF-16BE'))
else:
def is_surrogate(c):
ordc = ord(c)
return (ordc >= 55296) and (ordc < 56320)
def closure(data): # count function for "narrow" interpreter
u'returns the number of Unicode code points in a unicode string'
return len(data) - len(filter(is_surrogate, data))
return closure
assert codepoint_count(u'hello \U0001f44d') == 7
assert codepoint_count(u'hello \ud83d\udc4d') == 7
- 1. Jak uzyskać szerokość wyświetlania połączonych znaków Unicode w Pythonie 3?
- 2. Jak znaleźć jedną liczbę w ciągu znaków w Pythonie?
- 3. Jak uzyskać liczbę znaków w std :: string?
- 4. jak uzyskać liczbę "#" w ciągu znaków?
- 5. Usuwanie modyfikatorów znaków Unicode
- 6. Wyświetlanie znaków Unicode znaków iOS w Internecie
- 7. Jak nakładać i wyrównywać ciągi znaków Unicode za pomocą znaków specjalnych w pythonie?
- 8. Jak uzyskać liczbę znaków w łańcuchu w języku Transact SQL, "w inny sposób"
- 9. Unicode i `dekodowania()` w Pythonie
- 10. Jak policzyć liczbę unikalnych znaków w pliku?
- 11. Jak uzyskać wartości całkowite z ciągu znaków w Pythonie?
- 12. Jak używać znaków Unicode w ciągu Pythona
- 13. Jak wstawić n znaków w Pythonie
- 14. Lista znaków alfabetu Unicode
- 15. Drukowanie znaków Unicode PHP
- 16. Zastępowanie znaków Unicode w PostgreSQL
- 17. Python - pyparsing znaków unicode
- 18. Uzyskaj liczbę słów z ciągu znaków w Unicode (w dowolnym języku)
- 19. Jak przekonwertować punkty kodowe Unicode do ich reprezentacji znaków?
- 20. Jak przekonwertować ciąg znaków na znak Unicode?
- 21. znaków Unicode nie pokazuje
- 22. druku znaków Unicode
- 23. Jak wygenerować "dużą" liczbę losową w Pythonie?
- 24. JTextField: Jak ograniczyć liczbę znaków?
- 25. Jak uzyskać liczbę wyliczeń?
- 26. Konwertowanie znaków Unicode na ciąg znaków
- 27. Jak uzyskać "widoczną" długość łączenia ciągu znaków Unicode w języku Python?
- 28. Jak podzielić ciąg znaków Unicode na wiele znaków Unicode w języku C#?
- 29. Jak zliczyć liczbę znaków w zmiennej Bash?
- 30. Jak odczytać nieograniczoną liczbę znaków w C
Nie próbuj zapisywać 'u '\ ud834 \ udd0c''. Surogany nie są poprawnymi punktami kodowymi Unicode, więc nie powinieneś polegać na ich zachowaniu w łańcuchach lub długości działającej poprawnie. –
Aby wyjaśnić: 'u'blah'' w Pythonie pojęciowo reprezentuje sekwencję punktów kodu Unicode. Nie powinieneś w nich umieszczać binarnej reprezentacji UTF-16. –
Jeśli usunąłeś sentencję o kodowaniu i dekodowaniu ze swojego pytania i dodałeś ją jako odpowiedź, prawdopodobnie bym ją przegłosował, ponieważ uważam, że jest to najbardziej * poprawna * rzecz, aby uzyskać to, o co prosisz. – SingleNegationElimination