用户定义的异常:<unprintable ... object>

Emm*_*uel 9 python exception python-2.7

我试图在python 2.7中定义我自己的异常类,派生自BaseException.

class NestedCommentException(BaseException):
    """
    Exception for nested comments
    """
    def __init__(self, file_path, list_lines):
        self.file_path = file_path
        self.list_lines = list_lines

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return 'File {0} contains nested comments at lines {1}'.format(self.file_path, ', '.join(self.list_lines))
Run Code Online (Sandbox Code Playgroud)

但扔它时,它无法打印:raise NestedCommentException(file_path, list_lines)触发器

Traceback (most recent call last):
  File "D:\DATA\FP12210\My Documents\Outils\SVN\05_impl\2_tools\svn_tag_setup.py", line 85, in <module>
    tag_checks()
  File "D:\DATA\FP12210\My Documents\Outils\SVN\05_impl\2_tools\svn_tag_setup.py", line 66, in tag_checks
    check_nested_comments(ddl_path)
  File "D:\DATA\FP12210\My Documents\Outils\SVN\05_impl\2_tools\svn_tag_setup.py", line 54, in check_nested_comments
    raise NestedCommentException(file_path, list_lines)
NestedCommentException: <unprintable NestedCommentException object>
Run Code Online (Sandbox Code Playgroud)

你能解释为什么会发生这种情况,即使我定义__str____repr__方法?

Anu*_*yal 7

我的猜测是你有unicode in file_pathlist_lines变量dues,没有unicode功能它没有在控制台上打印.

或者任何其他异常__str__会导致这种奇怪的行为,最好的方法是捕获异常并看看发生了什么,也使用调试器

def __str__(self):
    try:
        s =  'File {0} contains nested comments at lines {1}'.format(self.file_path, ', '.join(self.list_lines))
    except Exception,e:
        print "-----",type(e),e
    return s
Run Code Online (Sandbox Code Playgroud)


Alo*_*dal 7

TL; DR

当你看到这个东西时,它基本上意味着__str__()你的对象中出现了某种异常.因此,除非问题在第一眼看上去是微不足道的(例如被遗忘的"%s"),否则

  • __str__主体包装在一个try/except子句中作为Anurag建议,或者

  • 实例化您的异常并__str__在traceback模块外部手动调用(或您可能已覆盖的任何方法),以便获得异常的完整描述.

分析

实际上这<unprintable MyException object>可以来自traceback模块中的各种函数,当试图获取一个字符串(即"可打印")版本的值(异常)时,它

  1. 打电话str()给它,如果出现任何问题,

  2. 尝试将其视为unicode并将其转换为ASCII,如果仍然出现任何问题

  3. 只需打印上面的表示.

负责任的代码(2.6和2.7中相同):

def _some_str(value):
    try:
        return str(value)
    except Exception:
        pass
    try:
        value = unicode(value)
        return value.encode("ascii", "backslashreplace")
    except Exception:
        pass
    return '<unprintable %s object>' % type(value).__name__
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,来自呼叫或呼叫的任何异常都在此过程中停止,并且仅给出"神秘"表示.str()unicode.encode()

关于回溯模块与Python解释器的注意事项

traceback文档告诉我们的相反:

它在打印堆栈跟踪时完全模仿了Python解释器的行为.

Python解释器给出的表示在这里略有不同.与"不可打印"消息相反,解释器只显示异常的名称,也停止任何实际异常.

这是一个简单的脚本,演示了所有三种方法:将异常留给Python解释器,使用traceback模块或手动调用函数.

#!/usr/bin/python

import sys, traceback

class Boom(Exception):

    def __init__(self, foo, bar, baz):
        self.foo, self.bar, self.baz = foo, bar, baz

    def __str__(self):
        return ("boom! foo: %s, bar: %s, baz: "     # ouch! forgot an %s!
                % (self.foo, self.bar, self.baz))

def goBoom(): raise Boom(foo='FOO', bar='BAR', baz='BAZ')

if __name__ == "__main__":

    if sys.argv[1].startswith("i"):
        goBoom()
        # __main__.Boom

    elif sys.argv[1].startswith("t"):
        try:    goBoom()
        except: traceback.print_exc(file=sys.stdout)
        # Boom: <unprintable Boom object>

    elif sys.argv[1].startswith("m"):
        e = Boom(foo='FOO', bar='BAR', baz='BAZ')
        e.__str__()
        # TypeError: not all arguments converted during string formatting

    else: pass
Run Code Online (Sandbox Code Playgroud)