В Python, как распечатать сообщение об ошибке без печати трассировки и закрыть программу, когда условие не выполняется?

Я видел похожие вопросы к этому, но никто из них действительно не обратился к трекбеку. Если у меня такой класс,

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" (в allcaps), тогда я хочу, чтобы он создавал настраиваемое сообщение об ошибке и завершал всю программу, а также не показывая трассировку.

Если ошибка встречается, единственное, что нужно распечатать, будет выглядеть примерно так (я использую 3 в качестве примера, форматирование - это не проблема).

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

Я не очень придирчивый к тому, что это объект класса исключения, поэтому в этом аспекте нет проблемы. Поскольку я буду использовать это в цикле while, просто, если elif просто повторяет сообщение снова и снова (потому что, очевидно, я не закрываю цикл). Я видел sys.exit(), но также печатает гигантский блок красного текста, если я не использую его правильно. Я не хочу улавливать исключение в моем цикле, потому что в том же модуле есть другие классы, в которых мне нужно реализовать что-то вроде этого.

Ответ 1

Вы можете использовать try:, а затем except Exception as inst: Что вам нужно сделать, это дать вам сообщение об ошибке в переменной inst, и вы можете распечатать аргументы об ошибке с помощью inst.args. Попробуйте распечатать его и посмотреть, что произойдет, и любой элемент в inst.args - тот, который вы ищете.

EDIT Вот пример, который я попробовал с питонами 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'
>>> 

EDIT 2: для закрытия программы вы всегда можете raise и ошибки, или вы можете использовать sys.exit()

Ответ 2

Вы можете отключить трассировку, ограничив ее глубину.

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>

Ответ 3

В общем случае, если вы хотите поймать любое исключение, кроме 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

Обратите внимание, что в случае создания нескольких исключений выводится только одно сообщение.

Этот ответ предназначен для улучшения одного из The-IT.

Ответ 4

Если вы хотите избавиться от какой-либо трассировки для таможенных исключений и иметь номер строки, вы можете сделать этот трюк

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

Ответ 5

Самый чистый способ, который я знаю, - использовать sys.excepthook.

Вы реализуете функцию трех аргументов, которая принимает type, value и traceback и делает все, что угодно (скажем, только печатает значение) и назначает эту функцию sys.excepthook.

Вот пример:

import sys

def excepthook(type, value, traceback):
    print(value)

sys.excepthook = excepthook

raise ValueError('hello')

Это доступно как для python 2, так и для python 3.