【问题标题】:Print an error message without printing a traceback and close the program when a condition is not met打印错误消息而不打印回溯,并在不满足条件时关闭程序
【发布时间】:2013-07-21 00:38:58
【问题描述】:

我见过与此类似的问题,但没有一个真正解决引用问题。 如果我有这样的课

class Stop_if_no_then():
    def __init__(self, value one, operator, value_two, then, line_or_label, line_number):
        self._firstvalue = value_one
        self._secondvalue = value_two
        self._operator = operator
        self._gohere = line_or_label
        self._then = then
        self._line_number = line_number

    def execute(self, OtherClass):
        "code comparing the first two values and making changes etc"

我希望我的执行方法能够做的是,如果 self._then 不等于字符串“THEN”(全部大写),那么我希望它引发自定义错误消息并终止整个程序,同时也不显示回溯。

如果遇到错误,唯一应该打印出来的东西看起来像(我以 3 为例,格式不是问题)。

`Syntax Error (Line 3): No -THEN- present in the statement.`

我对它实际上是一个异常类对象并不是很挑剔,所以这方面没有问题。由于我将在 while 循环中使用它,简单的 if, elif 只是一遍又一遍地重复消息(因为显然我没有关闭循环)。我见过 sys.exit() 但它也会打印出一大块红色文本,除非我没有正确使用它。我不想在循环中捕获异常,因为在同一个模块中还有其他类我需要在其中实现类似的东西。

【问题讨论】:

    标签: python exception error-handling customization traceback


    【解决方案1】:

    您可以通过限制其深度来关闭回溯。

    Python 2.x

    import sys
    sys.tracebacklimit = 0
    

    Python 3.x

    在 Python 3.5.2 和 3.6.1 中,将 tracebacklimit 设置为 0 似乎没有预期的效果。这是一个已知的bug。请注意,-1 也不起作用。不过,将其设置为 None 似乎确实有效,至少目前是这样。

    >>> import sys
    
    >>> sys.tracebacklimit = 0
    >>> raise Exception
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Exception
    
    >>> sys.tracebacklimit = -1
    >>> raise Exception
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Exception
    
    >>> sys.tracebacklimit = None
    >>> raise Exception
    Exception
    

    尽管如此,无论好坏,如果引发多个异常,它们仍然可以被打印出来。例如:

    socket.gaierror: [Errno -2] Name or service not known
    
    During handling of the above exception, another exception occurred:
    
    urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>
    

    【讨论】:

    • sys.tracebacklimit = 0 现在可以在 Python 3.7 上正常工作。 sys.tracebacklimit = None 在我的情况下不起作用。
    • &gt;&gt;&gt; sys.tracebacklimit = 0 &gt;&gt;&gt; raise TypeError('asdas') 输出:TypeError: asdas
    【解决方案2】:

    可以使用 SystemExit 异常:

    except Exception as err:
        raise SystemExit(err)
    

    https://docs.python.org/3/library/exceptions.html

    【讨论】:

    【解决方案3】:

    您可以使用try:,然后使用except Exception as inst: 这将在名为 inst 的变量中为您提供错误消息,您可以使用inst.args 打印出错误的参数。尝试将其打印出来看看会发生什么,inst.args 中的任何项目是否都是您要查找的项目。

    编辑这是我尝试使用 pythons IDLE 的示例:

    >>> try:
        open("epik.sjj")
    except Exception as inst:
        d = inst
    
    
    >>> d
    FileNotFoundError(2, 'No such file or directory')
    >>> d.args
    (2, 'No such file or directory')
    >>> d.args[1]
    'No such file or directory'
    >>> 
    

    编辑2:至于关闭程序,您始终可以raise 和错误,或者您可以使用sys.exit()

    【讨论】:

    • d.args 中的“2”是什么,错误消息“没有这样的文件或目录”是否可自定义(如果我创建了自己的异常类对象)?
    • 老实说,我不知道 2 是什么,但这并不重要。我正在向您展示如何自己找到错误消息。 “没有这样的文件或目录”是一个字符串,您可以将其放入变量中,然后执行您想做的任何事情。 errorMessage = d.args[1]
    • 该特定代码行的实际错误是FileNotFoundError: [Errno 2] No such file or directory: 'epik.sjj',所以这就是 2 的来源。 .args 是错误所有部分的元组。
    • 为什么不只是一个简单的print('blah-blah-blah') 而不是`d = inst'?
    • @The-IT 2 第一个参数来自errno module,是errno.ENOENT 的值。第二个参数'No such file or directory'os.strerror(errno.ENOENT) 的输出。
    【解决方案4】:

    我所知道的最简洁的方法是使用sys.excepthook

    您实现了一个接受typevaluetraceback 的三参数函数,并执行您喜欢的任何操作(例如,只打印值)并将该函数分配给sys.excepthook

    这是一个例子:

    import sys
    
    def excepthook(type, value, traceback):
        print(value)
    
    sys.excepthook = excepthook
    
    raise ValueError('hello')
    

    这在 python 2 和 python 3 中都可用。

    【讨论】:

    【解决方案5】:

    如果您想摆脱海关例外的任何追溯并拥有行号, 你可以做到这一点

    Python 3

    import sys
    import inspect
    
    class NoTraceBackWithLineNumber(Exception):
        def __init__(self, msg):
            try:
                ln = sys.exc_info()[-1].tb_lineno
            except AttributeError:
                ln = inspect.currentframe().f_back.f_lineno
            self.args = "{0.__name__} (line {1}): {2}".format(type(self), ln, msg),
            sys.exit(self)
    
    class MyNewError(NoTraceBackWithLineNumber):
        pass
    
    raise MyNewError("Now TraceBack Is Gone")
    

    将给出此输出,并使 raise 关键字无用

    MyNewError (line 16): Now TraceBack Is Gone
    

    【讨论】:

    • 你也可以继承SystemExit
    【解决方案6】:

    一般来说,如果您想捕获除SystemExit 之外的任何异常,并在没有回溯的情况下退出异常消息,请定义您的main 函数如下:

    >>> import sys
    
    >>> def main():
    ...     try:
    ...         # Run your program from here.
    ...         raise RandomException  # For testing
    ...     except (Exception, KeyboardInterrupt) as exc:
    ...         sys.exit(exc)
    ... 
    >>> main()
    name 'RandomException' is not defined
    
    $ echo $?
    1
    

    请注意,在引发多个异常的情况下,只会打印一条消息。

    此答案旨在改进one by The-IT

    【讨论】:

      【解决方案7】:

      “异常链接可以通过使用from None来禁用” - Python docs

      >>> try:
      ...     open('database.sqlite')
      ... except IOError:
      ...     raise RuntimeError from None
      
      Traceback (most recent call last):
        File "<stdin>", line 4, in <module>
      

      【讨论】:

      • 这就是我需要的。在 try 块中无法避免 SystemExit(err)。谢谢
      猜你喜欢
      • 1970-01-01
      • 2014-02-06
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多