【问题标题】:User-defined exception: <unprintable ... object>用户定义的异常:<unprintable ... object>
【发布时间】:2012-10-16 21:05:16
【问题描述】:

我尝试在 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)triggers

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__ 方法,您能否解释一下为什么会发生这种情况?

【问题讨论】:

  • 您是否有理由从BaseException 继承而不仅仅是Exception
  • 好吧,我首先从object 创建了这个类,我有:TypeError: exceptions must be old-style classes or derived from BaseException, not NestedCommentException。我试图让它源自Exception,同样的行为。
  • Exception 派生自 BaseException 并且应该用于用户定义的异常。
  • 也许变量 self.file_path 或 self.list_lines 以某种方式搞砸了。尝试从 str 方法中删除它们,看看会发生什么。
  • 使用 raise 的简单测试,那么你在做什么不同呢?你能看到你是如何用什么变量来提高它的吗?

标签: python exception python-2.7


【解决方案1】:

我的猜测是您在 file_pathlist_lines 变量中有 unicode,因为它没有在没有 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

【讨论】:

  • 问题确实存在于__str__(准确地说是', '.join(self.list_lines))。谢谢!
【解决方案2】:

TL;DR

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

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

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

分析

实际上这个&lt;unprintable MyException object&gt;可以来自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__

如您所见,来自str() 调用或unicode.encode() 调用的任何异常都会在此过程中停止,只给出“神秘”的表示。

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

traceback documentation 告诉我们的相反:

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

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

这里是a simple script,它演示了所有三种方法:将异常留给 Python 解释器、使用回溯模块或手动调用函数。

#!/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

【讨论】:

    猜你喜欢
    • 2015-07-05
    • 2015-02-27
    • 1970-01-01
    • 2016-10-07
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2016-09-10
    相关资源
    最近更新 更多