Как я могу конвертировать Юникод в верхний регистр, чтобы напечатать его? - PullRequest
37 голосов
/ 08 апреля 2009

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

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

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

EXÁMPLE

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

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

Ответы [ 5 ]

57 голосов
/ 08 апреля 2009

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

 >>> print u'exámple'.upper()
 EXÁMPLE
18 голосов
/ 08 апреля 2009

В 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().

Как и в моем случае, если ваш терминал не совместим с юникодом / utf-8, лучшее, на что вы можете надеяться, это либо шестнадцатеричное представление символов (например, моего), либо его преобразование с потерями, используя s.decode('utf-8').upper().encode('ascii', 'replace'), что в «EX? MPLE». Если вы не можете заставить свой терминал показывать юникод, запишите вывод в файл в формате utf-8 и откройте его в своем любимом редакторе.

9 голосов
/ 11 сентября 2010

Во-первых, я сейчас использую только 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 с опусканием'), так что пока вы остаетесь вне блоков Latin Extended-X ( проверьте их, они могут принести сюрпризы), вы могли бы на самом деле использовать этот метод. конечно, я не проверял правильность отображений.

наконец, вот что я поместил в мой раздел загрузки приложения py3k: метод, который переопределяет кодировку, которую sys.stdout видит, с числовыми ссылками на символы (NCR) как запасной вариант; это приводит к тому, что печать на стандартный вывод никогда не вызовет ошибку кодирования 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 с этим из будущего импортного заклинания литералов Unicode.

и в заключение, цитируя цитату: «Глиф Лефковиц лучше всего говорит в своей статье Кодировка :

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

обновление: только что найденный python 3 правильно преобразует AT LATIN SMALL LETTER LONG S в S при вводе заглавных букв. аккуратный!

4 голосов
/ 08 апреля 2009

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

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

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

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

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

0 голосов
/ 31 марта 2018

Попробуйте:

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