Как я могу преобразовать Юникод в верхний регистр, чтобы распечатать его?
-
05-09-2019 - |
Вопрос
У меня есть это:
>>> print 'example'
example
>>> print 'exámple'
exámple
>>> print 'exámple'.upper()
EXáMPLE
Что мне нужно сделать, чтобы напечатать:
EXÁMPLE
(Где буква "а" получает свое точное ударение, но в верхнем регистре.)
Я использую Python 2.6.
Решение
Я думаю, это так же просто, как не сначала преобразуйте в ASCII.
>>> print u'exámple'.upper()
EXÁMPLE
Другие советы
В python 2.x просто преобразуйте строку в юникод перед вызовом upper().Используя ваш код, который находится в формате utf-8 на этой веб-странице:
>>> s = 'exámple'
>>> s
'ex\xc3\xa1mple' # my terminal is not utf8. c3a1 is the UTF-8 hex for á
>>> s.decode('utf-8').upper()
u'EX\xc1MPLE' # c1 is the utf-16 aka unicode for á
Призыв к decode
переводит его из текущего формата в юникод.Затем вы можете преобразовать его в какой-либо другой формат, например utf-8, с помощью encode.Если бы символ был, скажем, в iso-8859-2 (в данном случае чешский и т.д.), вы бы вместо этого использовали s.decode('iso-8859-2').upper()
.
Как и в моем случае, если ваш терминал не совместим с unicode / utf-8, лучшее, на что вы можете надеяться, - это либо шестнадцатеричное представление символов (как у меня), либо преобразовать его с потерями, используя s.decode('utf-8').upper().encode('ascii', 'replace')
, что приводит к 'EX?MPLE'.Если вы не можете заставить свой терминал отображать юникод, запишите выходные данные в файл в формате utf-8 и откройте его в своем любимом редакторе.
во-первых, в наши дни я использую только python 3.1;его главное достоинство заключается в устранении неоднозначности байтовых строк из объектов unicode.это делает подавляющее большинство текстовых манипуляций намного безопаснее, чем это было раньше.принимая во внимание триллионы вопросов пользователей, касающихся проблем с кодированием python 2.x, u'äbc
соглашение python 2.1 было просто ошибкой;с явным bytes
и bytearray
, жизнь становится намного проще.
во-вторых, если py3k не ваш вкус, то попробуйте использовать from __future__ import unicode_literals
, так как это будет имитировать поведение py3k на python 2.6 и 2.7.это позволило бы избежать (легко совершаемой) ошибки, которую вы совершили, сказав print 'exámple'.upper()
.по сути, это то же самое, что и в py3k: print( 'exámple'.encode( 'utf-8' ).upper() )
.сравните эти версии (для py3k):
print( 'exámple'.encode( 'utf-8' ).upper() )
print( 'exámple'.encode( 'utf-8' ).upper().decode( 'utf-8' ) )
print( 'exámple'.upper() )
Первый - это, в основном, то, что вы делали, когда использовали голую строку 'exámple'
, при условии , что вы установили кодировку по умолчанию на utf-8
(согласно заявлению BDFL, установка кодировки по умолчанию во время выполнения - плохая идея, поэтому в py2 вам придется обмануть это, сказав import sys; reload( sys ); sys.setdefaultencoding( 'utf-8' )
;я представляю лучшее решение для py3k ниже).когда вы смотрите на выходные данные этих трех строк:
b'EX\xc3\xa1MPLE'
EXáMPLE
EXÁMPLE
вы можете видеть это, когда upper()
был применен к первому тексту, он действовал на байты, а не на символы.python позволяет upper()
метод для байтов, но он определяется только для интерпретации байтов в US-ASCII.поскольку utf-8 использует значения внутри 8 бит, но снаружи из US-ASCII (от 128 до 255, которые не используются US-ASCII), на них не повлияет upper()
, поэтому, когда мы декодируем обратно во второй строке, мы получаем этот строчный á
.наконец, третья строка делает это правильно, и да, сюрприз, python, похоже, осознает, что Á
соответствует ли заглавная буква á
.я провел быстрый тест, чтобы увидеть, какие символы python 3 не преобразует между верхним и нижним регистром:
for cid in range( 3000 ):
my_chr = chr( cid )
if my_chr == my_chr.upper() and my_chr == my_chr.lower():
say( my_chr )
при просмотре списка обнаруживается очень мало случаев использования латинских, кириллических или греческих букв;большая часть выходных данных состоит из неевропейских символов и знаков препинания.единственные символы, которые, как я смог обнаружить, python ошибся, - это Ԥ /ԥ (\u0524, \u0525, 'кириллическая {заглавная | маленькая} буква pe с потомком'), поэтому, пока вы остаетесь за пределами латинских блоков Extended-X (проверьте их, они могут преподнести сюрпризы), вы действительно можете использовать этот метод.конечно, я не проверял правильность сопоставлений.
наконец, вот что я поместил в раздел загрузки моего приложения py3k:метод , который переопределяет кодировку sys.stdout
видит, с числовыми ссылками на символы (NCRS) в качестве запасного варианта;это приводит к тому, что при печати в стандартный вывод никогда не возникнет ошибка кодировки unicode.когда я работаю на ubuntu, _sys.stdout.encoding
является utf-8
;когда та же программа запускается в Windows, это может быть что-то необычное, например cp850
.вывод может показаться странным, но приложение запускается без создания исключения на этих недалеких терминалах.
#===========================================================================================================
# MAKE STDOUT BEHAVE IN A FAILSAFE MANNER
#-----------------------------------------------------------------------------------------------------------
def _harden_stdout():
"""Ensure that unprintable output to STDOUT does not cause encoding errors; use XML character references
so any kind of output gets a chance to render in a decipherable way."""
global _sys_TRM
_sys.stdout = _sys_TRM = _sys_io.TextIOWrapper(
_sys.stdout.buffer,
encoding = _sys.stdout.encoding,
errors = 'xmlcharrefreplace',
line_buffering = true )
#...........................................................................................................
_harden_stdout()
еще один совет:при тестировании всегда старайтесь print repr( x )
или аналогичная вещь, которая раскрывает идентичность x
.всевозможные недоразумения могут возникнуть, если вы просто print x
в py2 и x
является либо строкой октета, либо объектом unicode.это очень озадачивает и склонно вызывать много почесываний в затылке.как я уже сказал, попробуйте перейти хотя бы на py26, используя это из будущего заклинания import unicode literals.
и в заключение процитирую цитату:" Глиф Лефковиц лучше всего говорит об этом в своей статье Кодирование:
Я полагаю, что в контексте этого обсуждения термин "строка" не имеет смысла.Есть текст, и есть данные, ориентированные на байты (которые могут очень хорошо представлять текст, но еще не преобразованы в него).В типах Python, Текст в формате unicode.Данные - это str.Идея "текста, отличного от Юникода", - это просто ожидающая своего появления ошибка программирования ".
Обновить:только что обнаружил, что python 3 корректно преобразует ſ ЛАТИНСКУЮ СТРОЧНУЮ БУКВУ ДЛИНОЙ S в S при использовании верхнего регистра.аккуратно!
Я думаю, что здесь нам немного не хватает предыстории:
>>> type('hello')
<type 'str'>
>>> type(u'hello')
<type 'unicode'>
Пока вы используете строки "unicode" вместо "собственных" строк, такие операторы, как upper(), будут работать с учетом unicode.FWIW, Python 3 использует unicode по умолчанию, что делает различие в значительной степени неуместным.
Берем строку из unicode
Для str
а затем возвращаемся к unicode
является неоптимальным во многих отношениях, и многие библиотеки будут выдавать выходные данные в юникоде, если вы этого захотите;поэтому старайтесь использовать только unicode
создавайте объекты для строк внутренне всякий раз, когда вы можете.
Попробуй это:
s = 'exámple'
print unicode(s).upper()