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

38

我有这个:

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

如何打印:

EXÁMPLE

(字母 'a' 大写时如何获得重音符号。)

我正在使用 Python 2.6。

5个回答

60

我认为这很简单,只需先转换为ASCII。

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

1
如果我输入 s = 'exámñple',如何将 s 正确地以大写形式打印出来? - Alex. S.
我的意思是,我如何在不出现UnicodeDecodeError错误的情况下将s转换为Unicode?(我之前使用的是u''+s) - Alex. S.
2
那是另一个问题,但你必须将sysencoding设置为utf。在这里看一下:https://dev59.com/KXVD5IYBdhLWcg3wWaVh#8020 - Bartosz Radaczyński

18
在Python 2.x中,在调用upper()函数之前,只需将字符串转换为Unicode即可。在此网页上使用的是UTF-8格式的代码:

在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 格式的文件,并在您喜欢的编辑器中打开它。

10

首先,我现在只使用 Python 3.1;它的主要优点在于将字节字符串与 unicode 对象进行了区分。这使得大多数文本操作比过去更加安全。考虑到关于 Python 2.x 编码问题的无数用户问题,Python 2.1 的 u'äbc 惯例只是一个错误;有了明确的 bytesbytearray,生活变得更加轻松。

其次,如果你不喜欢 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() )
第一个问题,基本上是你使用裸字符串'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 视图的方法,作为备选方案使用数值字符引用(NCRs),这样打印到标准输出时将永远不会引发 Unicode 编码错误。当我在 Ubuntu 上工作时,_sys.stdout.encodingutf-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的标识。如果您在py2中只打印x,并且x是八位字节字符串或unicode对象,则可能会出现各种误解。这非常令人困惑,容易引起很多烦恼。正如我所说,尝试至少使用来自未来的导入unicode文字的py26。

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

  

我相信,在这个讨论的背景下,“字符串”这个术语是毫无意义的。有文本和面向字节的数据(可以很好地表示文本,但尚未转换为文本)。在Python类型中,Text是unicode。Data是str。“非Unicode文本”的想法只是一种等待发生错误的编程错误。

更新:刚刚发现python 3正确地将ſ LATIN SMALL LETTER LONG S转换为S,当大写时。不错!


5

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

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

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

只要您使用“unicode”字符串而不是“native”字符串,像upper()这样的运算符将考虑到unicode。值得一提的是,Python 3默认使用unicode,使得区别在很大程度上变得无关紧要。
将字符串从“unicode”转换为“str”,然后再转换回“unicode”在许多方面都不太理想,并且许多库将在需要时生成unicode输出;因此,尽可能只在内部使用“unicode”对象作为字符串。

-2

试一下:

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

这是一个已有八年历史的问题,有一个被接受的答案,顺便说一下,它几乎与你的答案完全相同。我们可能需要的是一个可行的替代方案。请确保你的答案提供了这个方案。 - baduker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接