【问题标题】:How can I convert Unicode to uppercase to print it?如何将 Unicode 转换为大写进行打印?
【发布时间】:2010-10-18 04:04:54
【问题描述】:

我有这个:

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

打印需要做什么:

EXÁMPLE

('a' 的重音符号是大写的。)

我使用的是 Python 2.6。

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • 如果我使用 s = 'exámñple',如何正确打印大写的 s?
    • 我的意思是,如何在没有此错误的情况下将 s 转换为 unicode UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 2 (我使用的是 u''+s)跨度>
    • 那是另一个问题,但您必须将 sysencoding 设置为 utf。看这里:stackoverflow.com/questions/5419/…
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

      unicodestr 然后返回unicode 的字符串在很多方面都不是最理想的,如果你想要的话,许多库会产生unicode 输出;所以尽量在内部使用 unicode 对象作为字符串。

      【讨论】:

        【解决方案4】:

        首先,这些天我只使用 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 使用 US-ASCII 的 8 位但 的值(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, '西里尔 {capital|small} letter pe with descender'),所以只要你留在拉丁扩展 X 块之外(看看那些,他们可能会产生惊喜),你可能真的会使用那个方法。当然,我没有检查映射的正确性。

        最后,这是我放入 py3k 应用程序启动部分的内容:一种重新定义编码sys.stdout 的方法,使用数字字符引用 (NCR) 作为后备;这意味着打印到标准输出将永远不会引发 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 中 print x 并且 x 是八位字节字符串或 unicode 对象,则可能会出现各种误解。这是非常令人费解的,容易引起很多头疼。正如我所说,尝试至少从未来的导入 unicode 文字咒语中转移到 py26。

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

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

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

        【讨论】:

          【解决方案5】:

          试试看:

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

          【讨论】:

          • 这是一个已有 8 年历史的问题,有一个公认的答案,顺便说一句,它几乎和你的一样。我们在这里可能需要一个可行的替代方案。确保你的答案提供了这一点。
          猜你喜欢
          • 2021-10-05
          • 2011-12-25
          • 2017-01-26
          • 1970-01-01
          • 1970-01-01
          • 2015-11-08
          • 2014-12-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多