Python 3 — exceptions handling

What are exceptions in Python?

Python has built-in exceptions which can output an error. If an error occurs while running the program, it’s called an exception.

If an exception occurs, the type of exception is shown. Exceptions needs to be dealt with or the program will crash. To handle exceptions, the block is used.

Some exceptions you may have seen before are , or but there are many more.

All exceptions in Python inherit from the class BaseException. If you open the Python interactive shell and type the following statement it will list all built-in exceptions:

The idea of the try-except clause is to handle exceptions (errors at runtime). The syntax of the try-except block is:

1234
try:    <do something>except Exception:    <handle the error>

The idea of the try-except block is this:

  • try: the code with the exception(s) to catch. If an exception is raised, it jumps straight into the except block.

  • except: this code is only executed if an exception occured in the try block. The except block is required with a try block, even if it contains only the pass statement.

It may be combined with the else and finally keywords.

  • else: Code in the else block is only executed if no exceptions were raised in the try block.

  • finally: The code in the finally block is always executed, regardless of if a an exception was raised or not.

The try-finally Clause

You can use a finally: block along with a try: block. The finally block is a place to put any code that must execute, whether the try-block
raised an exception or not. The syntax of the try-finally statement is this −

try:
   You do your operations here;
   ......................
   Due to any exception, this may be skipped.
finally:
   This would always be executed.
   ......................

You cannot use else clause as well along with a finally clause.

Example

#!/usr/bin/python

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
finally:
   print "Error: can\'t find file or read data"

If you do not have permission to open the file in writing mode, then this will produce the following result −

Error: can't find file or read data

Same example can be written more cleanly as follows −

#!/usr/bin/python

try:
   fh = open("testfile", "w")
   try:
      fh.write("This is my test file for exception handling!!")
   finally:
      print "Going to close the file"
      fh.close()
except IOError:
   print "Error: can\'t find file or read data"

When an exception is thrown in the try block, the execution immediately passes to the finally block. After all the statements in the finally block are executed, the exception is raised again and is handled in the except statements if present in the next higher layer of the try-except statement.

Что такое Traceback в Python?

Трассировка (Traceback) — это отчет, содержащий вызовы функций, сделанные в вашем коде в определенный момент. Трассировка известна под многими именами, включая stack trace (трассировку стека), stack traceback (трассировку стека), backtrace (обратную трассировку) и, возможно, другие. В Python используется термин traceback.

Когда ваша программа выдает исключение, Python отображает трассировку, чтобы помочь вам узнать, что пошло не так. Ниже приведен пример, иллюстрирующий эту ситуацию:

# example.py
def greet(someone):
    print('Hello, ' + someon)

greet('Chad')

Здесь вызывается функция greet() с параметром someone. Однако в greet() это имя переменной не используется. Вместо этого было ошибочно указано переменная someon в вызове print().

Примечание. В этом руководстве предполагается, что вы знаете что такое исключения в Python. Если вы незнакомы или просто хотите освежиться, то вам следует почитать Python Exceptions: Введение.

Когда вы запустите эту программу, вы получите следующий traceback:

$ python example.py
Traceback (most recent call last):
  File "/path/to/example.py", line 4, in <module>
    greet('Chad')
  File "/path/to/example.py", line 2, in greet
    print('Hello, ' + someon)
NameError: name 'someon' is not defined

Этот вывод traceback содержит всю информацию, необходимую для диагностики проблемы. Последняя строка вывода сообщает вам, какой тип исключения был сгенерирован вместе с некоторой соответствующей информацией об этом исключении. Предыдущие строки указывают на код, который привел к возникновению исключения.

В приведенной выше traceback исключением был NameError, что означает, что имеется ссылка на какое-то имя (переменная, функция, класс), которое не было определено. В нашем примере использовано имя — someon.

В последней строке в этом случае достаточно информации, чтобы помочь вам решить проблему. Поиск кода по имени someon, который является орфографической ошибкой, укажет вам правильное направление. Однако часто ваш код намного сложнее.

8.3. Handling Exceptions¶

It is possible to write programs that handle selected exceptions. Look at the
following example, which asks the user for input until a valid integer has been
entered, but allows the user to interrupt the program (using Control-C or
whatever the operating system supports); note that a user-generated interruption
is signalled by raising the exception.

>>> while True
...     try
...         x = int(input("Please enter a number: "))
...         break
...     except ValueError
...         print("Oops!  That was no valid number.  Try again...")
...

The statement works as follows.

  • First, the try clause (the statement(s) between the and
    keywords) is executed.

  • If no exception occurs, the except clause is skipped and execution of the
    statement is finished.

  • If an exception occurs during execution of the try clause, the rest of the
    clause is skipped. Then if its type matches the exception named after the
    keyword, the except clause is executed, and then execution
    continues after the statement.

  • If an exception occurs which does not match the exception named in the except
    clause, it is passed on to outer statements; if no handler is
    found, it is an unhandled exception and execution stops with a message as
    shown above.

A statement may have more than one except clause, to specify
handlers for different exceptions. At most one handler will be executed.
Handlers only handle exceptions that occur in the corresponding try clause, not
in other handlers of the same statement. An except clause may
name multiple exceptions as a parenthesized tuple, for example:

... except (RuntimeError, TypeError, NameError):
...     pass

A class in an clause is compatible with an exception if it is
the same class or a base class thereof (but not the other way around — an
except clause listing a derived class is not compatible with a base class). For
example, the following code will print B, C, D in that order:

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in B, C, D]:
    try
        raise cls()
    except D
        print("D")
    except C
        print("C")
    except B
        print("B")

Note that if the except clauses were reversed (with first), it
would have printed B, B, B — the first matching except clause is triggered.

The last except clause may omit the exception name(s), to serve as a wildcard.
Use this with extreme caution, since it is easy to mask a real programming error
in this way! It can also be used to print an error message and then re-raise
the exception (allowing a caller to handle the exception as well):

import sys

try
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err
    print("OS error: {0}".format(err))
except ValueError
    print("Could not convert data to an integer.")
except
    print("Unexpected error:", sys.exc_info()[])
    raise

The … statement has an optional else
clause, which, when present, must follow all except clauses. It is useful for
code that must be executed if the try clause does not raise an exception. For
example:

for arg in sys.argv1:]:
    try
        f = open(arg, 'r')
    except OSError
        print('cannot open', arg)
    else
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

The use of the clause is better than adding additional code to
the clause because it avoids accidentally catching an exception
that wasn’t raised by the code being protected by the …
statement.

When an exception occurs, it may have an associated value, also known as the
exception’s argument. The presence and type of the argument depend on the
exception type.

The except clause may specify a variable after the exception name. The
variable is bound to an exception instance with the arguments stored in
. For convenience, the exception instance defines
so the arguments can be printed directly without having to
reference . One may also instantiate an exception first before
raising it and add any attributes to it as desired.

>>> try
...     raise Exception('spam', 'eggs')
... except Exception as inst
...     print(type(inst))    # the exception instance
...     print(inst.args)     # arguments stored in .args
...     print(inst)          # __str__ allows args to be printed directly,
...                          # but may be overridden in exception subclasses
...     x, y = inst.args     # unpack args
...     print('x =', x)
...     print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

If an exception has arguments, they are printed as the last part (‘detail’) of
the message for unhandled exceptions.

Exception handlers don’t just handle exceptions if they occur immediately in the
try clause, but also if they occur inside functions that are called (even
indirectly) in the try clause. For example:

Built-in exceptions

Exception Cause of Error
AssertionError if statement fails.
AttributeError if attribute assignment or reference fails.
EOFError if the functions hits end-of-file condition.
FloatingPointError if a floating point operation fails.
GeneratorExit Raise if a generator’s method is called.
ImportError if the imported module is not found.
IndexError if index of a sequence is out of range.
KeyError if a key is not found in a dictionary.
KeyboardInterrupt if the user hits interrupt key (Ctrl+c or delete).
MemoryError if an operation runs out of memory.
NameError if a variable is not found in local or global scope.
NotImplementedError by abstract methods.
OSError if system operation causes system related error.
OverflowError if result of an arithmetic operation is too large to be represented.
ReferenceError if a weak reference proxy is used to access a garbage collected referent.
RuntimeError if an error does not fall under any other category.
StopIteration by function to indicate that there is no further item to be returned by iterator.
SyntaxError by parser if syntax error is encountered.
IndentationError if there is incorrect indentation.
TabError if indentation consists of inconsistent tabs and spaces.
SystemError if interpreter detects internal error.
SystemExit by function.
TypeError if a function or operation is applied to an object of incorrect type.
UnboundLocalError if a reference is made to a local variable in a function or method, but no value has been bound to that variable.
UnicodeError if a Unicode-related encoding or decoding error occurs.
UnicodeEncodeError if a Unicode-related error occurs during encoding.
UnicodeDecodeError if a Unicode-related error occurs during decoding.
UnicodeTranslateError if a Unicode-related error occurs during translating.
ValueError if a function gets argument of correct type but improper value.
ZeroDivisionError if second operand of division or modulo operation is zero.

User-defined Exceptions

Python has many standard types of exceptions, but they may not always serve your purpose.Your program can have your own type of exceptions.

To create a user-defined exception, you have to create a class that inherits from Exception.

1234
class LunchError(Exception):    passraise LunchError("Programmer went to lunch")

You made a user-defined exception named LunchError in the above code. You can raise this new exception if an error occurs.

Outputs your custom error:

Your program can have many user-defined exceptions. The program below throws exceptions based on a new projects money:

1234567891011
class NoMoneyException(Exception):    passclass OutOfBudget(Exception):    passbalance = int(input("Enter a balance: "))if balance < 1000:    raise NoMoneyExceptionelif balance > 10000:    raise OutOfBudget

Here are some sample runs:

It is a good practice to put all user-defined exceptions in a separate file (exceptions.py or errors.py). This is common practice in standard modules too.

If you are a beginner, then I highly recommend this book.

Python try…finally

The statement in Python can have an optional clause. This clause is executed no matter what, and is generally used to release external resources.

For example, we may be connected to a remote data center through the network or working with a file or a Graphical User Interface (GUI).

In all these circumstances, we must clean up the resource before the program comes to a halt whether it successfully ran or not. These actions (closing a file, GUI or disconnecting from network) are performed in the clause to guarantee the execution.

Here is an example of file operations to illustrate this.

This type of construct makes sure that the file is closed even if an exception occurs during the program execution.

Raising an Exceptions

You can raise exceptions in several ways by using the raise statement. The general syntax for the raise statement is as follows.

Syntax

raise ]]

Here, Exception is the type of exception (for example, NameError) and argument is a value for the exception argument. The argument is optional; if not supplied, the exception argument is None.

The final argument, traceback, is also optional (and rarely used in practice), and if present, is the traceback object used for the exception.

Example

An exception can be a string, a class or an object. Most of the exceptions that the Python core raises are classes, with an argument that is an instance of the class. Defining new exceptions is quite easy and can be done as follows −

def functionName( level ):
   if level < 1:
      raise "Invalid level!", level
      # The code below to this would not be executed
      # if we raise the exception

Note: In order to catch an exception, an «except» clause must refer to the same exception thrown either class object or simple string. For example, to capture above exception, we must write the except clause as follows −

try:
   Business Logic here...
except "Invalid level!":
   Exception handling here...
else:
   Rest of the code here...

Python user defined exceptions

We can create our own exceptions if we want. We do it by defining a
new exception class.

user_defined.py

#!/usr/bin/env python

# user_defined.py


class BFoundEx(Exception):

    def __init__(self, value):
        self.par = value

    def __str__(self):
        return f"BFoundEx: b character found at position {self.par}"


string = "There are beautiful trees in the forest."

pos = 0

for i in string:

    try:

        if i == 'b':
            raise BFoundEx(pos)
        pos = pos + 1

    except BFoundEx as e:
        print(e)

In our code example, we have created a new exception. The exception is derived
from the base class. If we find any occurrence of
letter b in a string, we our exception.

$ ./user_defined.py
'BFoundEx: b character found at position 10'

Создание настраиваемого класса исключения

Мы можем создать собственный класс исключения, расширив класс Exception. Лучше всего создать базовое исключение, а затем наследовать другие классы. Вот несколько примеров.

class EmployeeModuleError(Exception):
    """Base Exception Class for our Employee module"""
    pass


class EmployeeNotFoundError(EmployeeModuleError):
    """Error raised when employee is not found in the database"""

    def __init__(self, emp_id, msg):
        self.employee_id = emp_id
        self.error_message = msg


class EmployeeUpdateError(EmployeeModuleError):
    """Error raised when employee update fails"""

    def __init__(self, emp_id, sql_error_code, sql_error_msg):
        self.employee_id = emp_id
        self.error_message = sql_error_msg
        self.error_code = sql_error_code

По соглашению об именах к имени класса исключения добавляется суффикс «Ошибка».

Assertions in Python

An assertion is a sanity-check that you can turn on or turn off when you are done with your testing of the program.

  • The easiest way to think of an assertion is to liken it to a raise-if statement (or to be more accurate, a raise-if-not statement). An expression is tested, and if the result comes up false, an exception is raised.

  • Assertions are carried out by the assert statement, the newest keyword to Python, introduced in version 1.5.

  • Programmers often place assertions at the start of a function to check for valid input, and after a function call to check for valid output.

The assert Statement

When it encounters an assert statement, Python evaluates the accompanying expression, which is hopefully true. If the expression is false, Python raises an AssertionError exception.

The syntax for assert is −

assert Expression

If the assertion fails, Python uses ArgumentExpression as the argument for the AssertionError. AssertionError exceptions can be caught and handled like any other exception, using the try-except statement. If they are not handled, they will terminate the program and produce a traceback.

Example

Here is a function that converts a given temperature from degrees Kelvin to degrees Fahrenheit. Since 0° K is as cold as it gets, the function bails out if it sees a negative temperature −

#!/usr/bin/python3

def KelvinToFahrenheit(Temperature):
   assert (Temperature >= 0),"Colder than absolute zero!"
   return ((Temperature-273)*1.8)+32

print (KelvinToFahrenheit(273))
print (int(KelvinToFahrenheit(505.78)))
print (KelvinToFahrenheit(-5))

When the above code is executed, it produces the following result −

32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!

Other Changes

Some changes to the language were made as part of the same project.

New Builtin Functions

Two new intrinsic functions for class testing were introduced
(since the functionality had to be implemented in the C API, there was
no reason not to make it accessible to Python programmers).

returns true iff class D is derived
from class C,
directly or indirectly. issubclass(C, C) always returns true. Both
arguments must be class objects.

returns true iff x is an
instance of C or of a
(direct or indirect) subclass of C. The first argument may hyave any
type; if x is not an instance of any class, isinstance(x, C) always
returns false. The second argument must be a class object.

Sequence Unpacking

Previous Python versions require an exact type match between the
left hand and right hand side of «unpacking» assignments, e.g.

As part of the same project, the right hand side of either statement can be
any sequence with exactly three items. This makes it possible to
extract e.g. the errno and strerror values from an IOError exception
in a backwards compatible way:

The same approach works for the SyntaxError exception, with the
proviso that the info part is not always present:

Exceptions versus Syntax Errors

Syntax errors occur when the parser detects an incorrect statement. Observe the following example:

The arrow indicates where the parser ran into the syntax error. In this example, there was one bracket too many. Remove it and run your code again:

This time, you ran into an exception error. This type of error occurs whenever syntactically correct Python code results in an error. The last line of the message indicated what type of exception error you ran into.

Instead of showing the message , Python details what type of exception error was encountered. In this case, it was a . Python comes with various built-in exceptions as well as the possibility to create self-defined exceptions.

Когда использовать исключения¶

Как правило, один и тот же код можно написать и с использованием
исключений, и без них.

Например, этот вариант кода:

while True
    a = input("Введите число: ")
    b = input("Введите второе число: ")
    try
        result = int(a)int(b)
    except ValueError
        print("Поддерживаются только числа")
    except ZeroDivisionError
        print("На ноль делить нельзя")
    else
        print(result)
        break

Можно переписать таким образом без try/except (файл
try_except_divide.py):

while True
    a = input("Введите число: ")
    b = input("Введите второе число: ")
    if a.isdigit() and b.isdigit():
        if int(b) == 
            print("На ноль делить нельзя")
        else
            print(int(a)int(b))
            break
    else
        print("Поддерживаются только числа")

Но далеко не всегда аналогичный вариант без использования исключений
будет простым и понятным.

Важно в каждой конкретной ситуации оценивать, какой вариант кода более
понятный, компактный и универсальный — с исключениями или без

try/except¶

Если вы повторяли примеры, которые использовались ранее, то наверняка
были ситуации, когда выскакивала ошибка. Скорее всего, это была ошибка
синтаксиса, когда не хватало, например, двоеточия.

Как правило, Python довольно понятно реагирует на подобные ошибки, и их
можно исправить.

Тем не менее, даже если код синтаксически написан правильно, могут
возникать ошибки. В Python эти ошибки называются исключения (exceptions).

Примеры исключений:

In 1]: 2
-----------------------------------------------------
ZeroDivisionError division by zero

In 2]: 'test' + 2
-----------------------------------------------------
TypeError must be str, not int

В данном случае возникло два исключения: ZeroDivisionError и
TypeError.

Чаще всего можно предсказать, какого рода исключения возникнут во время
исполнения программы.

Например, если программа на вход ожидает два числа, а на выходе выдает
их сумму, а пользователь ввел вместо одного из чисел строку, появится
ошибка TypeError, как в примере выше.

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

Примечание

Когда в программе возникает исключение, она сразу завершает работу.

Для работы с исключениями используется конструкция :

In 3]: try
   ...     2
   ... except ZeroDivisionError
   ...     print("You can't divide by zero")
   ...
You can't divide by zero

Конструкция try работает таким образом:

  • сначала выполняются выражения, которые записаны в блоке try
  • если при выполнения блока try не возникло никаких исключений, блок except пропускается,
    и выполняется дальнейший код
  • если во время выполнения блока try в каком-то месте возникло исключение,
    оставшаяся часть блока try пропускается

    • если в блоке except указано исключение, которое возникло, выполняется код в блоке except
    • если исключение, которое возникло, не указано в блоке except,
      выполнение программы прерывается и выдается ошибка

Обратите внимание, что строка в блоке try не выводится:

In 4]: try
   ...     print("Let's divide some numbers")
   ...     2
   ...     print('Cool!')
   ... except ZeroDivisionError
   ...     print("You can't divide by zero")
   ...
Let's divide some numbers
You can't divide by zero

В конструкции try/except может быть много except, если нужны разные
действия в зависимости от типа ошибки.

Например, скрипт divide.py делит два числа введенных пользователем:

# -*- coding: utf-8 -*-

try
    a = input("Введите первое число: ")
    b = input("Введите второе число: ")
    print("Результат: ", int(a)int(b))
except ValueError
    print("Пожалуйста, вводите только числа")
except ZeroDivisionError
    print("На ноль делить нельзя")

Примеры выполнения скрипта:

$ python divide.py
Введите первое число: 3
Введите второе число: 1
Результат:  3

$ python divide.py
Введите первое число: 5
Введите второе число: 0
На ноль делить нельзя

$ python divide.py
Введите первое число: qewr
Введите второе число: 3
Пожалуйста, вводите только числа

В данном случае исключение ValueError возникает, когда пользователь
ввел строку вместо числа, во время перевода строки в число.

Исключение ZeroDivisionError возникает в случае, если второе число было
равным 0.

Если нет необходимости выводить различные сообщения на ошибки ValueError
и ZeroDivisionError, можно сделать так (файл divide_ver2.py):

# -*- coding: utf-8 -*-

try
    a = input("Введите первое число: ")
    b = input("Введите второе число: ")
    print("Результат: ", int(a)int(b))
except (ValueError, ZeroDivisionError):
    print("Что-то пошло не так...")

Проверка:

$ python divide_ver2.py
Введите первое число: wer
Введите второе число: 4
Что-то пошло не так...

$ python divide_ver2.py
Введите первое число: 5
Введите второе число: 0
Что-то пошло не так...

Built-in Exceptions

The table below shows built-in exceptions that are usually raised in Python:

Exception Description
ArithmeticError Raised when an error occurs in numeric calculations
AssertionError Raised when an assert statement fails
AttributeError Raised when attribute reference or assignment fails
Exception Base class for all exceptions
EOFError Raised when
the input() method hits an «end of file» condition (EOF)
FloatingPointError Raised when a floating point calculation fails
GeneratorExit Raised when a generator is closed (with the close() method)
ImportError Raised when an imported module does not exist
IndentationError Raised when indendation is not correct
IndexError Raised when an index of a sequence does not exist
KeyError Raised when a key does not exist in a dictionary
KeyboardInterrupt Raised when the user presses Ctrl+c,
Ctrl+z or Delete
LookupError Raised when errors raised cant be found
MemoryError Raised when a program runs out of memory
NameError Raised when a variable does not exist
NotImplementedError Raised when an abstract method requires an inherited class to override the
method
OSError Raised when a system related operation causes an error
OverflowError Raised when the result of a numeric calculation is too large
ReferenceError Raised when a weak reference object does not exist
RuntimeError Raised when an error occurs that do not belong to any specific expections
StopIteration Raised when the next() method of an iterator has no further values
SyntaxError Raised when a syntax error occurs
TabError Raised when indentation consists of tabs or spaces
SystemError Raised when a system error occurs
SystemExit Raised when the sys.exit() function is called
TypeError Raised when two different types are combined
UnboundLocalError Raised when a local variable is referenced before assignment
UnicodeError Raised when a unicode problem occurs
UnicodeEncodeError Raised when a unicode encoding problem occurs
UnicodeDecodeError Raised when a unicode decoding problem occurs
UnicodeTranslateError Raised when a unicode translation problem occurs
ValueError Raised when there is a wrong value in a specified data type
ZeroDivisionError Raised when the second operator in a division is zero

❮ Previous
Next ❯

User-Defined Exceptions

Python also allows you to create your own exceptions by deriving classes from the standard built-in exceptions.

Here is an example related to RuntimeError. Here, a class is created that is subclassed from RuntimeError. This is useful when you need to display more specific information when an exception is caught.

In the try block, the user-defined exception is raised and caught in the except block. The variable e is used to create an instance of the class Networkerror.

class Networkerror(RuntimeError):
   def __init__(self, arg):
      self.args = arg

So once you defined above class, you can raise the exception as follows −

try:
   raise Networkerror("Bad hostname")
except Networkerror,e:
   print e.args

Previous Page
Print Page

Next Page  

Base classes¶

The following exceptions are used mostly as base classes for other exceptions.

exception

The base class for all built-in exceptions. It is not meant to be directly
inherited by user-defined classes (for that, use ). If
is called on an instance of this class, the representation of
the argument(s) to the instance are returned, or the empty string when
there were no arguments.

The tuple of arguments given to the exception constructor. Some built-in
exceptions (like ) expect a certain number of arguments and
assign a special meaning to the elements of this tuple, while others are
usually called only with a single string giving an error message.

(tb)

This method sets tb as the new traceback for the exception and returns
the exception object. It is usually used in exception handling code like
this:

try
    ...
except SomeException
    tb = sys.exc_info()[2
    raise OtherException(...).with_traceback(tb)
exception

All built-in, non-system-exiting exceptions are derived from this class. All
user-defined exceptions should also be derived from this class.

exception

The base class for those built-in exceptions that are raised for various
arithmetic errors: , ,
.

exception

Raised when a related operation cannot be
performed.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector