用户定义的异常:<unprintable ... =“”object =“”> </unprintable>

时间:2012-10-26 15:14:19

标签: 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))

但扔掉它时,无法打印: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>

即使我定义了__str____repr__方法,您能解释一下为什么会这样吗?

2 个答案:

答案 0 :(得分:7)

我的猜测是你在没有unicode功能的控制台上没有打印file_pathlist_lines个变量的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

答案 1 :(得分:7)

TL; DR

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

  • __str__正文包装在try / except子句中作为Anurag建议,或者

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

分析

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

  1. 在其上调用str(),如果出现任何问题,

  2. 尝试将其视为unicode并将其转换为ASCII,如果还有其他任何内容 出错了

  3. 只需打印上述表示。

  4. 责任代码(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__
    

    正如您所看到的,来自str()调用或unicode.encode()调用的任何异常都会在此过程中停止,并且只会给出“神秘”的表示。< / p>

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

    traceback documentation告诉我们的内容相反:

      

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

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

    以下是a simple script演示所有三种方法:将异常留给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