Как я могу вызвать исключение в Python, чтобы позже его можно было перехватить с помощью блока except?
Ручное создание (выброс) исключения в Python
Ответы (9)
Как вручную генерировать исключение в Python?
Будьте конкретны в своем сообщении, например:
raise ValueError('A very specific bad thing happened.')
Не создавайте общих исключений
Избегайте повышения общего Exception. Чтобы поймать это, вам нужно будет поймать все другие более конкретные исключения, которые его подклассифицируют.
Проблема 1: Скрытие ошибок
raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.
Например:
def demo_bad_catch():
try:
raise ValueError('Represents a hidden bug, do not catch this')
raise Exception('This is the exception you expect to handle')
except Exception as error:
print('Caught this error: ' + repr(error))
>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)
Проблема 2: не поймаешь
И более конкретные уловы не улавливают общее исключение:
def demo_no_catch():
try:
raise Exception('general exceptions not caught by specific handling')
except ValueError as e:
print('we will not catch exception: Exception')
>>> demo_no_catch()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling
Рекомендации: raise инструкция
raise ValueError('A very specific bad thing happened')
который также позволяет передавать конструктору произвольное количество аргументов:
raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')
К этим аргументам обращается атрибут args объекта Exception. Например:
try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)
отпечатки
('message', 'foo', 'bar', 'baz')
В Python 2.5 к BaseException был добавлен фактический атрибут message, чтобы побудить пользователей создать подкласс Исключений и прекратить использование args, но введение message и первоначальное прекращение поддержки аргументов было отменено.
Лучшие Лрактики: пункт except
Находясь внутри предложения except, вы можете захотеть, например, зарегистрировать, что произошла ошибка определенного типа, а затем повторно вызвать. Лучший способ сделать это при сохранении трассировки стека - использовать оператор простого повышения. Например:
logger = logging.getLogger(__name__)
try:
do_something_in_app_that_breaks_easily()
except AppError as error:
logger.error(error)
raise # just this!
# raise AppError # Don't do this, you'll lose the stack trace!
Не изменяйте свои ошибки ... но если вы настаиваете.
Вы можете сохранить трассировку стека (и значение ошибки) с помощью sys.exc_info(), но это гораздо более подвержено ошибкам и имеет проблемы совместимости между Python 2 и 3, предпочитайте использовать чистый raise сделать ререйз.
Чтобы объяснить - sys.exc_info() возвращает тип, значение и трассировку.
type, value, traceback = sys.exc_info()
Это синтаксис Python 2 - обратите внимание, что он несовместим с Python 3:
raise AppError, error, sys.exc_info()[2] # avoid this.
# Equivalently, as error *is* the second object:
raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
Если вы хотите, вы можете изменить то, что происходит с вашим новым повышением - например, установка нового args для экземпляра:
def error():
raise ValueError('oops!')
def catch_error_modify_message():
try:
error()
except ValueError:
error_type, error_instance, traceback = sys.exc_info()
error_instance.args = (error_instance.args[0] + ' <modification>',)
raise error_type, error_instance, traceback
И мы сохранили всю трассировку при изменении аргументов. Обратите внимание, что это не лучшая практика и это недопустимый синтаксис в Python 3 (что значительно усложняет работу по сохранению совместимости).
>>> catch_error_modify_message()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in catch_error_modify_message
File "<stdin>", line 2, in error
ValueError: oops! <modification>
В Python 3:
raise error.with_traceback(sys.exc_info()[2])
Еще раз: избегайте ручного управления трассировкой. Это менее эффективно и более подвержено ошибкам. А если вы используете потоки и sys.exc_info, вы можете даже получить неправильную трассировку (особенно если вы используете обработку исключений для потока управления - чего я лично стараюсь избегать).
Python 3, цепочка исключений
В Python 3 вы можете связать исключения, которые сохраняют трассировку:
raise RuntimeError('specific message') from error
Имейте в виду:
- это позволяет изменить тип возникшей ошибки, и
- это несовместимо с Python 2.
Устаревшие методы:
Их можно легко скрыть и даже попасть в производственный код. Вы хотите вызвать исключение, и их выполнение вызовет исключение, но не то, которое было задумано!
Действителен в Python 2, но не в Python 3:
raise ValueError, 'message' # Don't do this, it's deprecated!
Только действителен в более старых версиях Python (версии 2.4 и ниже), вы все еще можете видеть, как люди поднимают строки:
raise 'message' # really really wrong. don't do this.
Во всех современных версиях это фактически вызовет TypeError, потому что вы не поднимаете тип BaseException. Если вы не проверяете правильное исключение и у вас нет проверяющего, который знает о проблеме, оно может попасть в рабочую среду.
Пример использования
Я создаю исключения, чтобы предупредить потребителей о моем API, если они используют его неправильно:
def api_func(foo):
'''foo should be either 'baz' or 'bar'. returns something very useful.'''
if foo not in _ALLOWED_ARGS:
raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))
Создавайте свои собственные типы ошибок при необходимости
Я намеренно хочу сделать ошибку, чтобы она попала в исключение
Вы можете создавать свои собственные типы ошибок, если вы хотите указать, что с вашим приложением что-то не так, просто подклассифицируйте соответствующую точку в иерархии исключений:
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
и использование:
if important_key not in resource_dict and not ok_to_be_missing:
raise MyAppLookupError('resource is missing, and that is not ok.')
ValueError и сообщаете об этом как о типе Exception, и это ненужная потеря точности. repr(e) по крайней мере сообщит вам о типе.
- person Aaron Hall; 15.01.2021
raise TypeError("my message")
- person Gabriel Staples; 05.02.2021
TypeError, был вызовом конструктора класса! Теперь это имеет смысл. Таким образом, сообщение является общим аргументом конструктора для классов ошибок.
- person Gabriel Staples; 06.02.2021
НЕ ДЕЛАЙТЕ ЭТОГО. Поднимать голый
Exception- это абсолютно не правильное занятие; см. вместо этого отличный ответ Аарона Холла.
Не может быть ничего более питонического, чем это:
raise Exception("I know python!")
См. документацию по оператору повышения для Python, если вы хотите больше информации.
raise Exception("I know python!"), я не могу распечатать его след
- person alper; 19.05.2021
В Python3 есть 4 разных синтаксиса для исключения исключений:
1. raise exception
2. raise exception (args)
3. raise
4. raise exception (args) from original_exception
1. поднять исключение против 2. поднять исключение (аргументы)
Если вы используете raise exception (args) для создания исключения, тогда args будет напечатан при печати объекта исключения, как показано в примере ниже.
#raise exception (args)
try:
raise ValueError("I have raised an Exception")
except ValueError as exp:
print ("Error", exp) # Output -> Error I have raised an Exception
#raise execption
try:
raise ValueError
except ValueError as exp:
print ("Error", exp) # Output -> Error
3. повышение
raise без аргументов повторно вызывает последнее исключение. Это полезно, если вам нужно выполнить некоторые действия после перехвата исключения, а затем вы хотите его повторно возбудить. Но если раньше не было исключения, оператор raise вызывает TypeError Exception.
def somefunction():
print("some cleaning")
a=10
b=0
result=None
try:
result=a/b
print(result)
except Exception: #Output ->
somefunction() #some cleaning
raise #Traceback (most recent call last):
#File "python", line 8, in <module>
#ZeroDivisionError: division by zero
4. вызвать исключение (аргументы) из исходного_исключения
Этот оператор используется для создания цепочки исключений, в которой исключение, которое возникает в ответ на другое исключение, может содержать детали исходного исключения, как показано в примере ниже.
class MyCustomException(Exception):
pass
a=10
b=0
reuslt=None
try:
try:
result=a/b
except ZeroDivisionError as exp:
print("ZeroDivisionError -- ",exp)
raise MyCustomException("Zero Division ") from exp
except MyCustomException as exp:
print("MyException",exp)
print(exp.__cause__)
Вывод:
ZeroDivisionError -- division by zero
MyException Zero Division
division by zero
exception(args) exception (args)
- person Gloweye; 28.06.2019
raise exception(args) from None означает, что текущее активное исключение было обработано и больше не представляет интереса. В противном случае, если вы вызываете исключение внутри блока except, и оно не обрабатывается, трассировки для обоих исключений будут показаны разделенными сообщением «Во время обработки указанного выше исключения произошло другое исключение».
- person cg909; 04.04.2020
Для общего случая, когда вам нужно сгенерировать исключение в ответ на некоторые неожиданные условия, которые вы никогда не собираетесь перехватывать, а просто быстро вывести из строя, чтобы вы могли отлаживать оттуда, если это когда-либо произойдет - наиболее логичным кажется AssertionError:
if 0 < distance <= RADIUS:
#Do something.
elif RADIUS < distance:
#Do something.
else:
raise AssertionError("Unexpected value of 'distance'!", distance)
ValueError, чем для AssertionError, потому что нет проблем с утверждением (потому что здесь ничего не делается) - проблема в значении. Если в этом случае вам действительно нужен AssertionError, напишите assert distance > 0, 'Distance must be positive'. Но вы не должны проверять ошибки таким образом, потому что утверждения можно отключить (python -O).
- person Two-Bit Alchemist; 17.09.2015
-O.
- person Two-Bit Alchemist; 17.09.2015
Сначала прочтите существующие ответы, это всего лишь дополнение.
Обратите внимание, что вы можете вызывать исключения с аргументами или без них.
Пример:
raise SystemExit
выходит из программы, но вы можете захотеть узнать, что произошло, поэтому можете использовать это.
raise SystemExit("program exited")
это напечатает "программа завершена" в stderr перед закрытием программы.
raise SystemExit() не было бы лучшим выбором? Почему первый вообще работает?
- person burny; 01.10.2019
Просто обратите внимание: бывают случаи, когда вы НЕОБХОДИМО обрабатывать общие исключения. Если вы обрабатываете кучу файлов и регистрируете свои ошибки, вы можете захотеть перехватить любую ошибку, которая возникает для файла, зарегистрировать ее и продолжить обработку остальных файлов. В этом случае
try:
foo()
except Exception as e:
print(e) # Print out handled error
block - хороший способ сделать это. Тем не менее, вы все равно захотите raise определенные исключения, чтобы вы знали, что они означают.
Другой способ создания исключений - assert. Вы можете использовать assert, чтобы убедиться, что условие выполняется, если нет, тогда оно поднимет AssertionError. Дополнительные сведения см. здесь.
def avg(marks):
assert len(marks) != 0,"List is empty."
return sum(marks)/len(marks)
mark2 = [55,88,78,90,79]
print("Average of mark2:",avg(mark2))
mark1 = []
print("Average of mark1:",avg(mark1))
raise AssertionError()
- person cowbert; 24.09.2020
Для этого вам следует выучить инструкцию Raise в python. Он должен храниться внутри блока try. Пример -
try:
raise TypeError #remove TypeError by any other error if you want
except TypeError:
print('TypeError raised')
Вы также можете создать настраиваемые исключения. Например, если вы пишете библиотеку, очень полезно создать базовый класс исключения для вашего модуля, а затем иметь настраиваемые под-исключения, чтобы быть более конкретными.
Вы можете добиться этого следующим образом:
class MyModuleBaseClass(Exception):
pass
class MoreSpecificException(MyModuleBaseClass):
pass
# To raise custom exceptions, you can just
# use the raise keyword
raise MoreSpecificException
raise MoreSpecificException('message')
Если вас не интересует настраиваемый базовый класс, вы можете просто унаследовать свои настраиваемые классы исключений от обычного класса исключений, например Exception, TypeError, ValueError и т. Д.