6

我试图在 python 2.7.x 中引发异常,其中包含消息中的 unicode。我似乎无法让它工作。

是否不支持或不建议在错误消息中包含 unicode?还是我需要查看 sys.stderr?

 # -*- coding: utf-8 -*-
 class MyException(Exception):
  def __init__(self, value):
    self.value = value
  def __str__(self):
    return self.value
  def __repr__(self):
    return self.value
  def __unicode__(self):
    return self.value

desc = u'something bad with field \u4443'

try:
  raise MyException(desc)
except MyException as e:
  print(u'Inside try block : ' + unicode(e))

# here is what i wish to make work 
raise MyException(desc)

运行脚本会产生以下输出。在我的 try/except 中,我可以毫无问题地打印字符串。

我的问题不在尝试/除外。

Inside try block : something bad with field 䑃
Traceback (most recent call last):
  File "C:\Python27\lib\bdb.py", line 387, in run
    exec cmd in globals, locals
  File "C:\Users\ghis3080\r.py", line 25, in <module>
    raise MyException(desc)
MyException: something bad with field \u4443

提前致谢。

4

3 回答 3

2

这就是 Python 的工作原理。我相信您所看到的来自traceback._some_string()Python 核心库。在该模块中,完成堆栈跟踪后,该方法中的代码首先尝试使用 转换消息str(),然后如果引发异常,则使用 转换消息unicode(),然后使用 将其转换为 ascii encode("ascii", "backslashreplace")。您得到了有效的输出,并且一切正常,我的猜测是 Python 正在尽力对错误消息进行伪向下转换,以便无论平台执行它,它都会毫无问题地显示。这只是您角色的 unicode 代码点。它不会在您的try/except块中发生,因为这种转换是特定于产生堆栈跟踪的机制的(例如在未捕获的异常事件中)。

于 2012-11-06T18:27:22.607 回答
2

行为取决于 Python 版本和环境。在 Python 3 上,字符编码错误处理程序sys.stderr总是'backslashreplace'

from __future__ import unicode_literals, print_function
import sys

s = 'unicode "\u2323" smile'
print(s)
print(s, file=sys.stderr)
try:
    raise RuntimeError(s)
except Exception as e:
    print(e.args[0])
    print(e.args[0], file=sys.stderr)
    raise

蟒蛇3:

$ PYTHONIOENCODING=ascii:ignore python3 raise_unicode.py
unicode "" smile
unicode "\u2323" smile
unicode "" smile
unicode "\u2323" smile
Traceback (most recent call last):
  File "raise_unicode.py", line 8, in <module>
    raise RuntimeError(s)
RuntimeError: unicode "\u2323" smile

蟒蛇2

$ PYTHONIOENCODING=ascii:ignore python2 raise_unicode.py
unicode "" smile
unicode "" smile
unicode "" smile
unicode "" smile
Traceback (most recent call last):
  File "raise_unicode.py", line 8, in <module>
    raise RuntimeError(s)
RuntimeError

那是在我的系统上,错误消息在 python2 上被吃掉了。

注意:在 Windows 上,您可以尝试:

T:\> set PYTHONIOENCODING=ascii:ignore
T:\> python raise_unicode.py

为了比较:

$ python3 raise_unicode.py
unicode "⌣" smile
unicode "⌣" smile
unicode "⌣" smile
unicode "⌣" smile
Traceback (most recent call last):
  File "raise_unicode.py", line 8, in <module>
    raise RuntimeError(s)
RuntimeError: unicode "⌣" smile
于 2012-11-06T20:51:52.483 回答
1

在我的情况下,您的示例可以正常工作,打印出漂亮的 unicode。

但有时您在打印没有(或使用转义/反斜杠)unicode 字符的异常堆栈时会遇到很多问题。可以克服障碍并打印正常消息。

输出问题示例(Python 2.7,linux):

# -*- coding: utf-8 -*-
desc = u'something bad with field ¾'
raise SyntaxError(desc.encode('utf-8', 'replace'))

它将仅打印截断或拧紧的消息:

~/.../sources/C_patch$ python SO.py 
Traceback (most recent call last):
  File "SO.py", line 25, in <module>
    raise SyntaxError(desc)
SyntaxError

要实际查看未更改的 unicode,您可以将其编码为原始字节并输入异常对象:

# -*- coding: utf-8 -*-
desc = u'something bad with field ¾'
raise SyntaxError(desc.encode('utf-8', 'replace'))

这次您将看到完整的消息:

~/.../sources/C_patch$ python SO.py 
Traceback (most recent call last):
  File "SO.py", line 3, in <module>
    raise SyntaxError(desc.encode('utf-8', 'replace'))
SyntaxError: something bad with field ¾

如果您愿意,您可以value.encode('utf-8', 'replace')在构造函数中执行此操作,但如果出现系统异常,您必须在raise语句中执行此操作,就像在示例中一样。

提示取自这里:克服挫折:在 python2 中正确使用 unicode(有很多帮助程序的大库,所有这些都可以剥离到上面的示例)。

于 2014-11-27T11:48:39.457 回答