如何将Unicode转换为大写打印?
我有这个:
>>> 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中,只需要在调用upper()之前将string转换为unicode。 使用你的代码,这是在这个网页上的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()
。
就像我的情况一样,如果你的terminal不符合unicode / utf-8标准,你所希望的最好的结果就是用hex表示字符(像我的)或者用s.decode('utf-8').upper().encode('ascii', 'replace')
,这会导致“EX?MPLE”。 如果你不能让你的terminal显示unicode,把输出写到utf-8格式的文件中,并在你最喜欢的编辑器中打开。
首先,我现在只使用python 3.1; 它的核心优点是从unicode对象中消除了字节串的歧义。 这使得绝大多数文本操作比过去更安全。 考虑到有关Python 2.x编码问题的用户问题的数以万亿计,python 2.1的u'äbc
惯例只是一个错误; 与明确的bytes
和bytearray
,生活变得如此简单。
其次,如果py3k不是你的风格,那么尝试from __future__ import unicode_literals
,因为这将模仿Python 2.6和2.7 py3k的行为。 这个东西本来可以避免你在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() )
首先,基本上,当你使用一个纯string'exámple'
,你提供的默认编码设置为utf-8
(根据BDFL的声明,在运行时设置默认编码是一个坏主意,所以在py2,你将不得不欺骗它说import sys; reload( sys ); sys.setdefaultencoding( 'utf-8' )
;我为下面的py3k提出了一个更好的解决scheme)。 当你看这三行的输出时:
b'EX\xc3\xa1MPLE' EXáMPLE EXÁMPLE
你可以看到当upper()
被应用到第一个文本时,它对字节起作用,而不是在字符上。 python允许在字节upper()
方法,但是它只在US-ASCII字节解释上定义。 由于utf-8使用8位以内但US-ASCII(128到255,US-ASCII不使用upper()
,所以不会受upper()
影响,所以当我们在第二个行,我们得到那个小写的á
。 最后,第三行是正确的,是的,惊喜,python似乎意识到Á
是对应于á
的大写字母。 我跑了一个快速testing,看看什么字符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出错的唯一字符是des /ԥ(\ u0524,\ u0525,'cyrillic {capital | small}带下行字母的字母'),所以只要您停留在Latin Extended-X块之外看看那些,他们可能会产生惊喜),你可能实际上使用这种方法。 当然,我没有检查映射的正确性。
最后,这里是我的py3k应用程序引导部分:一种方法,重新定义编码sys.stdout
看到,与数字字符引用(NCR)作为后备; 这具有打印到标准输出将永远不会引起Unicode编码错误的效果。 当我在Ubuntu上工作时, _sys.stdout.encoding
是utf-8
; 当相同的程序在Windows上运行时,可能会像cp850
一样古怪。 输出可能看起来很牛,但是应用程序运行时没有在这些暗淡的terminal上引发exception。
#=========================================================================================================== # 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()
还有一点build议:在testing的时候,总是试着print repr( x )
或者类似的东西来揭示x
的身份。 如果你只是在py2中print x
而x
是一个八位string或一个unicode对象,那么所有的误解都会出现。 这是非常令人费解,容易引起很多头部划伤。 正如我所说的,尽量把这个从未来的导入Unicode文字咒语移到py26。
并引用一句话:“莱夫科维茨(Glyph Lefkowitz)在他的文章” 编码(Encoding) “中说得最好:
我相信在这个讨论中,“串”这个词是没有意义的。 有文本,并有字节为导向的数据(这可能很好地代表文本,但尚未转换成它)。 在Pythontypes中,Text是unicode。 数据是str。 “非Unicode文本”的想法只是一个等待发生的编程错误。“
更新:刚刚发现python 3正确转换s拉丁小字母长S为大写。 整齐!
我认为这里有一些我们缺less的背景:
>>> type('hello') <type 'str'> >>> type(u'hello') <type 'unicode'>
只要您使用“unicode”string而不是“native”string,像upper()这样的操作符就会以unicode的forms进行操作。 FWIW,Python 3默认使用unicode,使得区别在很大程度上不相关。
从unicode
到str
再到unicode
的string在许多方面都不是最理想的,许多库会根据需要产生unicode输出; 因此,只要有可能,就尽量只在内部使用unicode
对象。