【问题标题】:Python2.7 print unicode string still getting UnicodeEncodeError: 'ascii' codec can't encode character ... ordinal not in range(128)Python2.7打印Unicode字符串仍然得到UnicodeEncodeError:'ascii'编解码器无法编码字符......序数不在范围内(128)
【发布时间】:2017-05-24 12:38:21
【问题描述】:

一个简单的打印函数

def TODO(message):
    print(type(message))
    print(u'\n~*~ TODO ~*~ \n %s\n     ~*~\n' % message)

这样称呼

TODO(u'api servisleri için input check decorator gerekiyor')

导致此错误

<type 'unicode'>                                                                                 
Traceback (most recent call last):                                                               
  File "/srv/www/proj/__init__.py", line 38, in <module>                                      
    TODO(u'api servisleri için input check decorator gerekiyor')                                 
  File "/srv/www/proj/helpers/utils.py", line 33, in TODO                                     
    print(u'\n~*~ TODO ~*~ \n %s\n     ~*~\n' % message)                                         
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe7' in position 32: ordinal not in range(128)

但它可以在 ipython 控制台中运行

In [10]: TODO(u'api servisleri için input check decorator gerekiyor')
<type 'unicode'>

~*~ TODO ~*~ 
 api servisleri için input check decorator gerekiyor
     ~*~

这适用于 python 2.7.12,但在 2.7.9 中以某种方式失败。

我在这里做错了什么?

编辑:在烧瓶应用程序中调用函数失败,在 python 控制台中工作。

【问题讨论】:

  • 我刚刚从命令行在多个版本的python 2.6.6、2.7.9、2.7.10 和2.7.13 上尝试了您的代码,并且您的代码运行良好。
  • 听起来您的控制台语言环境已损坏并且默认为 ASCII。您使用的是什么操作系统?
  • 我假设您使用的是 Un*x 系统。见:stackoverflow.com/a/35839964/1554386
  • 在没有更多信息的情况下,我投票将其关闭为“不可重现”。这可能是一个简单的语言环境问题。
  • @AlastairMcCormack 都是 'UTF-8'

标签: python python-2.7 unicode python-unicode


【解决方案1】:

不同的终端(和 GUI)允许不同的编码。我手边没有最近的 ipython,但它显然能够处理字符串中的非 ASCII 0xe7 字符 ('ç')。但是,您的普通控制台使用的是 'ascii' 编码(在异常中按名称提及),它无法显示任何大于 0x7f 的字节。

如果您想将非 ASCII 字符串打印到 ASCII 控制台,您必须决定如何处理无法显示的字符。 str.encode 方法提供了几个选项:

str.encode([encoding[, errors]])

errors 可以设置不同的错误处理方案。 errors 的默认值为'strict',这意味着编码错误会引发UnicodeError。 其他可能的值为'ignore''replace''xmlcharrefreplace''backslashreplace' 以及通过codecs.register_error() 注册的任何其他名称,请参阅Codec Base Classes 部分。

这是一个示例,它在您的字符串上使用这四个替代错误处理程序中的每一个(没有TODO 添加的额外装饰):

#!/usr/bin/env python2
# -*- coding: utf-8 -*-

from __future__ import print_function

uni = u'api servisleri için input check decorator gerekiyor'
handlers = ['ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace']
for handler in handlers:
    print(handler + ':')
    print(uni.encode('ascii', handler))
    print()

输出:

ignore:
api servisleri iin input check decorator gerekiyor

replace:
api servisleri i?in input check decorator gerekiyor

xmlcharrefreplace:
api servisleri i&#231;in input check decorator gerekiyor

backslashreplace:
api servisleri i\xe7in input check decorator gerekiyor

这些输出中的哪一个最接近您想要的结果由您决定。

有关详细信息,请参阅 Python 2“Unicode HOWTO”和 Ned Batchelder 的“Pragmatic Unicode, or, How Do I Stop the Pain?”,也可作为 36 分钟的video from PyCon US 2012

编辑:...或者,您似乎已经发现,您的终端可以很好地显示 Unicode,但您的默认编码仍然设置为 'ascii',这比它更具限制性需要。

【讨论】:

    【解决方案2】:

    \xe7

    代表小 'ç' 的 utf-8 字符之一。 Python 2.7.9 可能使用 ASCII 编码。您可以在代表 Python 2.7.9 行为的任何 Python 版本中运行以下代码。

    import sys; 
    # -*- coding: utf-8 -*-
    
    def TODO(message):
        print(type(message))
        print(u'\n~*~ TODO ~*~ \n %s\n     ~*~\n' % message)
    
    message = u'api servisleri için input check decorator gerekiyor'
    encodedMessage = message.encode('ascii')
    
    print(sys.stdout.encoding)
    TODO(encodedMessage)
    

    会抛出异常

    Traceback(最近一次调用最后一次):文件“test.py”,第 9 行,在 encodedMessage = message.encode('ascii') UnicodeEncodeError: 'ascii' codec can't encode character '\xe7' in position 16: ordinal 不在范围内(128)

    所以,问题与解释器的编码规则有关。您可以自行编码或忽略。

    希望对你有用

    【讨论】:

      【解决方案3】:

      显然,打印功能与打印语句有点不同。

      https://docs.python.org/2.7/library/functions.html#print

      All non-keyword arguments are converted to strings like 
      str() does and written to the stream, separated by sep 
      and followed by end. 
      

      简单地说,编码unicode字符串就解决了

      msg = u'\n~*~ TODO ~*~ \n %s\n     ~*~\n' % message
      print(msg.encode("utf-8"))
      

      仍然不确定为什么它适用于 2.7.12,可能是语言环境问题?

      【讨论】:

      • 这不是答案。请参阅@Alastair 评论并修复您的环境。您正在做的是手动编码为 UTF-8,这在非 UTF8 终端上不起作用。将您的终端配置为向 Python 正确报告 UTF-8,print u'için' 将起作用。打印函数与语句是一条红鲱鱼,除非您使用from __future__ import print_function,否则 Python 2 没有打印功能。它在 Python 3 中变成了一个函数。
      • 两种环境具有相同的语言环境输出。正如我提到的文件中所述,这是打印功能的预期输出。这是打印功能失败的机器上的打印输出。 ╰─$ python Python 2.7.9 (default, Jun 29 2016, 13:08:31) [GCC 4.9.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. &gt;&gt;&gt; print u'için' için
      猜你喜欢
      • 2019-09-29
      • 2019-11-10
      • 2021-05-14
      • 2023-03-03
      • 1970-01-01
      • 2014-01-22
      • 2016-08-26
      • 2017-03-29
      • 2011-07-05
      相关资源
      最近更新 更多