В 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.