У меня есть это:
>>> print 'example'
example
>>> print 'exámple'
exámple
>>> print 'exámple'.upper()
EXáMPLE
Что мне нужно сделать для печати:
EXÁMPLE
(Где "a" получает свой акцент, но в верхнем регистре.)
Я использую Python 2.6.
У меня есть это:
>>> print 'example'
example
>>> print 'exámple'
exámple
>>> print 'exámple'.upper()
EXáMPLE
Что мне нужно сделать для печати:
EXÁMPLE
(Где "a" получает свой акцент, но в верхнем регистре.)
Я использую Python 2.6.
Я думаю, что это так просто, как не преобразование в 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, с помощью кодирования. Если персонаж находился, скажем, 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 в эти дни; его центральная заслуга состоит в том, чтобы иметь неоднозначные байтовые строки из объектов Юникода. это делает подавляющее большинство текстовых манипуляций намного более безопасными, чем это имело место. взвешивая триллионы пользовательских вопросов относительно проблем с кодировкой 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 )
просмотр списка показывает очень мало случаев латинских, кириллических или греческих букв; большая часть выходных данных - неевропейские символы и знаки препинания. единственными символами, которые я обнаружил, что питон ошибался, - это Ԥ/ԥ (\ u0524,\u0525, 'cyrillic {capital | small} letter pe с descender'), так что пока вы остаетесь за пределами латинских Extended-X блоков ( проверьте их, они могут дать сюрпризы), вы можете использовать этот метод. конечно, я не проверял правильность отображений.
Наконец, вот что я ввел в мой раздел загрузки приложения py3k: метод, который переопределяет кодировку sys.stdout
видит с численными символьными ссылками (NCR) как резерв; это приводит к тому, что печать на стандартный вывод никогда не вызовет ошибку кодирования в юникоде. когда я работаю над ubuntu, _sys.stdout.encoding
- utf-8
; когда одна и та же программа запускается в окнах, это может быть что-то странное, как 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.
и закрыть, цитируя цитату: "Глиф Лефковиц говорит, что лучше всего в своей статье Encoding:
Я считаю, что в контексте этого обсуждение, термин "строка" бессмысленны. Есть текст, и там это байт-ориентированные данные (которые могут хорошо представлять текст, но еще не преобразованный в него). В типах Python, Текст является unicode. Данные - str. Идея "текста, отличного от Юникода", является просто ошибка программирования ".
update: только что найденный python 3 правильно преобразует s LATIN SMALL LETTER LONG S в S при верхнем регистре. аккуратный!
Я думаю, что здесь немного фона, который нам не хватает:
>>> type('hello')
<type 'str'>
>>> type(u'hello')
<type 'unicode'>
Пока вы используете строки "unicode" вместо "родных" строк, операторы типа upper() будут работать с unicode. FWIW, Python 3 по умолчанию использует unicode, делая различие в значительной степени несущественным.
Взятие строки от unicode
до str
, а затем назад к unicode
является субоптимальным по-разному, и многие библиотеки будут выводить unicode-вывод, если вы этого хотите; поэтому старайтесь использовать только unicode
объекты для строк внутри, когда можете.