Как преобразовать Unicode в верхний регистр для его печати?

у меня есть это:

>>> print 'example'
example
>>> print 'exámple'
exámple
>>> print 'exámple'.upper()
EXáMPLE

что мне нужно сделать, чтобы напечатать:

EXÁMPLE

(где " a " получает свой accute акцент, но в верхнем регистре.)

Я использую Python 2.6.

5 ответов


Я думаю, что это так просто не сначала преобразование в ASCII.

 >>> print u'exámple'.upper()
 EXÁMPLE

в python 2.x, просто преобразуйте строку в unicode перед вызовом 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 берет его из текущего формата в Unicode. Затем вы можете преобразовать его в другой формат, например 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'. Если вы не можете заставить свой терминал показывать unicode, запишите выходные данные в файл в формате utf-8 и откройте его в своем любимом редакторе.


во-первых, я использую только python 3.1 в эти дни; его центральным достоинством является наличие неоднозначных строк байтов из объектов unicode. это делает подавляющее большинство текстовых манипуляций намного безопаснее, чем раньше. взвешивание в триллионах пользовательских вопросов, касающихся python 2.х проблем, кодировки,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 бит, но за пределами из нас-ASCII (128 до 255, которые не используются нами-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, 'кириллица {capital|small} letter pe с descender'), поэтому, пока вы остаетесь вне латинских блоков Extended-X (проверьте их, они могут дать сюрпризы), вы можете использовать этот метод. конечно, я не проверял правильность отображения.

наконец, вот что я положил в мое приложение py3k раздел Загрузки: метод, который переопределяет кодировку sys.stdout видит, с числовыми ссылками символов (NCRs) в качестве резервного; это имеет эффект, что печать на стандартный вывод никогда не вызовет ошибку кодирования unicode. когда я работаю над ubuntu,_sys.stdout.encoding и utf-8; когда та же программа работает в windows, это может быть что-то странное, как cp850. выход может выглядеть starnge, но приложение работает без создания исключения для тех, кто тупоумный терминалы.

#===========================================================================================================
# 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 с помощью будущего импорта литералов unicode.

и закрыть, цитируя цитату: "глиф Лефковиц говорит это лучше всего в своей статье кодирование:

я считаю, что в контексте этого обсуждение, термин "строка" бессмысленный. Есть текст, а есть байт-ориентированные данные (которые могут очень хорошо представляют текст, но пока нет преобразованный в него). В типах Python, Текст-Юникод. Данные стр. Идея "не-Unicode text" - это просто ошибка программирования, ожидающая случаться."

обновление: только что нашел на Python 3 Правильно преобразует ſ Латинская строчная буквы С С, когда uppercasing. ловко!


Я думаю, что есть немного фона, которого нам не хватает здесь:

>>> type('hello')
<type 'str'>

>>> type(u'hello')
<type 'unicode'>

пока вы используете строки "unicode "вместо" собственных " строк, операторы, такие как upper (), будут работать с unicode. Fwiw, Python 3 использует unicode по умолчанию, что делает различие в значительной степени неуместным.

взятие строки из unicode to str и обратно в unicode является неоптимальным во многих отношениях, и многие библиотеки будут производить вывод unicode, если вы этого хотите; поэтому попробуйте использовать только unicode объекты для строк внутри, когда вы можете.


попробуй:

s = 'exámple'
print unicode(s).upper()