如何将Unicode转换为大写以打印它?

时间:2009-04-07 20:41:47

标签: python unicode python-2.x case-sensitive uppercase

我有这个:

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

我需要做什么才能打印:

EXÁMPLE

('a'获得其精确的重音,但是大写。)

我正在使用Python 2.6。

5 个答案:

答案 0 :(得分:57)

我认为它就像首先转换为ASCII一样简单。

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

答案 1 :(得分:18)

在python 2.x中,只需在调用upper()之前将字符串转换为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。然后,您可以使用encode将其转换为其他格式,如utf-8。如果角色在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格式的文件,然后在您喜欢的编辑器中打开它。

答案 2 :(得分:9)

首先,我这几天只使用python 3.1;它的核心优点是从unicode对象中消除歧义字节串。这使得绝大多数文本操作比以前更加安全。在数以万计的用户关于python 2.x编码问题的问题中,python 2.1的u'äbc约定只是一个错误;明确bytesbytearray,生活变得如此简单。

其次,如果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,'cyrillic {capital | small}字母pe与descender'),所以只要你留在拉丁语Extended-X块之外(看看那些,他们可能会产生惊喜),你可能实际上使用那种方法。当然,我没有检查映射的正确性。

最后,这是我放入py3k应用程序引导部分的内容:重新定义编码sys.stdout的方法,数字字符引用(NCR)作为后备;这会导致打印到标准输出永远不会引发unicode编码错误。当我在ubuntu上工作时,_sys.stdout.encodingutf-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的身份。如果你在py2 print x只是x并且{{1}}是一个八位字符串或一个unicode对象,那么就会出现各种各样的误解。这是非常令人费解的,容易引起很多人头疼。正如我所说,尝试使用未来的导入unicode文字咒语至少移动到py26。

并关闭,引用一句话:“Glyph Lefkowitz在他的文章Encoding中说得最好:

  

我相信在此背景下   讨论,术语“字符串”是   无意义的。有文字,那里   是面向字节的数据(可能非常   很好地代表文本,但还没有   转换为它)。在Python类型中,   文字是unicode。数据是str。这个想法   “非Unicode文本”只是一个   编程错误等待发生。“

更新:刚刚发现python 3在大写时正确地将s LATIN SMALL LETTER LONG S转换为S.整齐!

答案 3 :(得分:4)

我认为我们在这里缺少一些背景知识:

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

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

只要你使用“unicode”字符串而不是“native”字符串,像upper()这样的运算符就会考虑使用unicode。 FWIW,Python 3默认使用unicode,使得区别在很大程度上无关紧要。

unicodestr然后回到unicode的字符串在很多方面都不是最理想的,如果你需要,许多库会产生unicode输出;所以尽可能在内部尝试仅使用unicode个字符串作为字符串。

答案 4 :(得分:-2)

试一试:

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