Обработка исключений в python
Содержание:
- User-Defined Exceptions
- Python hierarchy of exceptions
- Пример использования telnetlib¶
- Built-in exceptions
- User-defined Exceptions
- Some Built-In Warning Classes
- The try and except Block: Handling Exceptions
- Основные исключения
- Exception hierarchy¶
- Creating Custom Exception Class
- The Standard Exception Hierarchy
- Тело сообщения
- User-Defined Exceptions
- Вызов исключений
- Выявление определенных исключений
- 5.1. Base classes¶
- Catching Exceptions in Python
- Python try…finally
- Python Exception Handling Best Practices
- Советы
- Customizing Exception Classes
- What are exceptions in Python?
- 5.4. Exception hierarchy¶
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 have defined the 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
Python hierarchy of exceptions
The exceptions are organized in a hierarchy, being
the parent of all exceptions.
interrupt.py
#!/usr/bin/env python # interrupt.py try: while True: pass except KeyboardInterrupt: print("Program interrupted")
The script starts and endless cycle. If we press Ctrl+C,
we interrupt the cycle. Here, we caught the
exception.
Exception BaseException KeyboardInterrupt
This is the hierarchy of the exception.
interrupt2.py
#!/usr/bin/env python # interrupt2.py try: while True: pass except BaseException: print("Program interrupted")
This example works too. The also catches the
keyboard interruption; among other exceptions. This is not a good practice, however.
We should catch specific exceptions in our clauses.
Пример использования telnetlib¶
Файл 2_telnetlib.py:
import telnetlib import time from pprint import pprint def to_bytes(line): return f"{line}\n".encode("utf-8") def send_show_command(ip, username, password, enable, commands): with telnetlib.Telnet(ip) as telnet telnet.read_until(b"Username") telnet.write(to_bytes(username)) telnet.read_until(b"Password") telnet.write(to_bytes(password)) index, m, output = telnet.expect() if index == telnet.write(b"enable\n") telnet.read_until(b"Password") telnet.write(to_bytes(enable)) telnet.read_until(b"#", timeout=5) telnet.write(b"terminal length 0\n") telnet.read_until(b"#", timeout=5) time.sleep(3) telnet.read_very_eager() result = {} for command in commands telnet.write(to_bytes(command)) output = telnet.read_until(b"#", timeout=5).decode("utf-8") resultcommand = output.replace("\r\n", "\n") return result if __name__ == "__main__" devices = "192.168.100.1", "192.168.100.2", "192.168.100.3" commands = "sh ip int br", "sh arp" for ip in devices result = send_show_command(ip, "cisco", "cisco", "cisco", commands) pprint(result, width=120)
Так как методу write надо передавать байты и добавлять каждый раз перевод строки,
создана небольшая функция to_bytes, которая выполняет преобразование в байты и
добавление перевода строки.
Выполнение скрипта:
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.
Some Built-In Warning Classes
The Warning class is the base class for all the warnings. It has the following sub-classes.
- BytesWarning – bytes, and buffer related warnings, mostly related to string conversion and comparison.
- DeprecationWarning – warning about deprecated features
- FutureWarning – base class for warning about constructs that will change semantically in the future.
- ImportWarning – warning about mistakes in module imports
- PendingDeprecationWarning – warning about features that will be deprecated in future.
- ResourceWarning – resource usage warnings
- RuntimeWarning – warnings about dubious runtime behavior.
- SyntaxWarning – warning about dubious syntax
- UnicodeWarning – Unicode conversion-related warnings
- UserWarning – warnings generated by the user code
The try and except Block: Handling Exceptions
The and block in Python is used to catch and handle exceptions. Python executes code following the statement as a “normal” part of the program. The code that follows the statement is the program’s response to any exceptions in the preceding clause.
As you saw earlier, when syntactically correct code runs into an error, Python will throw an exception error. This exception error will crash the program if it is unhandled. The clause determines how your program responds to exceptions.
The following function can help you understand the and block:
The can only run on a Linux system. The in this function will throw an exception if you call it on an operating system other then Linux.
You can give the function a using the following code:
The way you handled the error here is by handing out a . If you were to run this code on a Windows machine, you would get the following output:
You got nothing. The good thing here is that the program did not crash. But it would be nice to see if some type of exception occurred whenever you ran your code. To this end, you can change the into something that would generate an informative message, like so:
Execute this code on a Windows machine:
When an exception occurs in a program running this function, the program will continue as well as inform you about the fact that the function call was not successful.
What you did not get to see was the type of error that was thrown as a result of the function call. In order to see exactly what went wrong, you would need to catch the error that the function threw.
The following code is an example where you capture the and output that message to screen:
Running this function on a Windows machine outputs the following:
The first message is the , informing you that the function can only be executed on a Linux machine. The second message tells you which function was not executed.
In the previous example, you called a function that you wrote yourself. When you executed the function, you caught the exception and printed it to screen.
Here’s another example where you open a file and use a built-in exception:
If file.log does not exist, this block of code will output the following:
This is an informative message, and our program will still continue to run. In the Python docs, you can see that there are a lot of built-in exceptions that you can use here. One exception described on that page is the following:
To catch this type of exception and print it to screen, you could use the following code:
In this case, if file.log does not exist, the output will be the following:
You can have more than one function call in your clause and anticipate catching various exceptions. A thing to note here is that the code in the clause will stop as soon as an exception is encountered.
Warning: Catching hides all errors…even those which are completely unexpected. This is why you should avoid bare clauses in your Python programs. Instead, you’ll want to refer to specific exception classes you want to catch and handle. You can learn more about why this is a good idea in this tutorial.
Look at the following code. Here, you first call the function and then try to open a file:
If the file does not exist, running this code on a Windows machine will output the following:
Inside the clause, you ran into an exception immediately and did not get to the part where you attempt to open file.log. Now look at what happens when you run the code on a Linux machine:
Here are the key takeaways:
- A clause is executed up until the point where the first exception is encountered.
- Inside the clause, or the exception handler, you determine how the program responds to the exception.
- You can anticipate multiple exceptions and differentiate how the program should respond to them.
- Avoid using bare clauses.
Основные исключения
Вы уже сталкивались со множеством исключений. Ниже изложен список основных встроенных исключений (определение в документации к Пайтону):
- Exception – то, на чем фактически строятся все остальные ошибки;
- AttributeError – возникает, когда ссылка атрибута или присвоение не могут быть выполнены;
- IOError – возникает в том случае, когда операция I/O (такая как оператор вывода, встроенная функция open() или метод объекта-файла) не может быть выполнена, по связанной с I/O причине: «файл не найден», или «диск заполнен», иными словами.
- ImportError – возникает, когда оператор import не может найти определение модуля, или когда оператор не может найти имя файла, который должен быть импортирован;
- IndexError – возникает, когда индекс последовательности находится вне допустимого диапазона;
- KeyError – возникает, когда ключ сопоставления (dictionary key) не найден в наборе существующих ключей;
- KeyboardInterrupt – возникает, когда пользователь нажимает клавишу прерывания(обычно Delete или Ctrl+C);
- NameError – возникает, когда локальное или глобальное имя не найдено;
- OSError – возникает, когда функция получает связанную с системой ошибку;
- SyntaxError — возникает, когда синтаксическая ошибка встречается синтаксическим анализатором;
- TypeError – возникает, когда операция или функция применяется к объекту несоответствующего типа. Связанное значение представляет собой строку, в которой приводятся подробные сведения о несоответствии типов;
- ValueError – возникает, когда встроенная операция или функция получают аргумент, тип которого правильный, но неправильно значение, и ситуация не может описано более точно, как при возникновении IndexError;
- ZeroDivisionError – возникает, когда второй аргумент операции division или modulo равен нулю;
Существует много других исключений, но вы вряд ли будете сталкиваться с ними так же часто. В целом, если вы заинтересованы, вы можете узнать больше о них в документации Пайтон.
Exception hierarchy¶
The class hierarchy for built-in exceptions is:
BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception +-- StopIteration +-- StopAsyncIteration +-- ArithmeticError | +-- FloatingPointError | +-- OverflowError | +-- ZeroDivisionError +-- AssertionError +-- AttributeError +-- BufferError +-- EOFError +-- ImportError | +-- ModuleNotFoundError +-- LookupError | +-- IndexError | +-- KeyError +-- MemoryError +-- NameError | +-- UnboundLocalError +-- OSError | +-- BlockingIOError | +-- ChildProcessError | +-- ConnectionError | | +-- BrokenPipeError | | +-- ConnectionAbortedError | | +-- ConnectionRefusedError | | +-- ConnectionResetError | +-- FileExistsError | +-- FileNotFoundError | +-- InterruptedError | +-- IsADirectoryError | +-- NotADirectoryError | +-- PermissionError | +-- ProcessLookupError | +-- TimeoutError +-- ReferenceError +-- RuntimeError | +-- NotImplementedError | +-- RecursionError +-- SyntaxError | +-- IndentationError | +-- TabError +-- SystemError +-- TypeError +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning +-- ResourceWarning
Creating Custom Exception Class
We can create a custom exception class by extending Exception class. The best practice is to create a base exception and then derive other exception classes. Here are some examples of creating user-defined exception classes.
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
The naming convention is to suffix the name of exception class with “Error”.
The Standard Exception Hierarchy
Behold the standard exception hierarchy. It is defined in the new
standard library module exceptions.py. Exceptions that were new since
Python 1.5 are marked with (*).
The root class for all exceptions is the new exception Exception.
From this, two additional classes are derived, StandardError, which is
the root class for all standard exceptions, and SystemExit. It is
recommended that user-defined exceptions in new code be derived from
Exception, although for backward compatibility reasons, this is not
required. Eventually this rule will be tightened.
SystemExit is derived from Exception because while it is an
exception, it is not an error.
Most standard exceptions are direct descendants of StandardError.
Some related exceptions are grouped together using an intermediate
class derived from StandardError; this makes it possible to catch
several different exceptions in one except clause, without using the
tuple notation.
We looked into introducing more groups of related exceptions,
but couldn’t decide on the best grouping. In a language as dynamic as
Python, it’s hard to say whether TypeError is a «program error», a
«runtime error» or an «environmental error», so we decided to leave it
undecided. It could be argued that NameError and AttributeError
should be derived from LookupError, but this is questionable and
depends entirely on the application.
Exception Class Definitions
The Python class definitions for the standard exceptions are
imported from the standard module «exceptions». You can’t change this
file thinking that the changes will automatically show up in the
standard exceptions; the builtin module expects the current hierarchy
as defined in exceptions.py.
Details on the standard exception classes are available in the
Python library reference manual’s entry for the
exceptions module.
Тело сообщения
Согласно спецификации HTTP — POST, PUT и менее распространенный метод PATCH, передают свои данные через тело сообщения, а не через параметры в строке запроса. Используя эти запросы, вы передатите полезную нагрузку в параметр соответствующей функции.
принимает словарь, список кортежей, байтов или файлоподобный объект.
Вы можете захотеть адаптировать данные, которые отправляете в теле запроса, к конкретным потребностям сервиса, с которым взаимодействуете.
Например, если тип содержимого вашего запроса — , вы можете отправить данные формы в виде словаря:
Вы также можете отправить данные в списке кортежей:
Если вам нужно отправить данные в формате JSON, вы можете использовать параметр . Когда вы передаете данные через , то Requests упорядочивает ваши данные и указывает за вас правильный заголовок .
httpbin.org это прекрасный ресурс, созданный автором . Это сервис, который принимает тестовые запросы и возвращает данные о запросе. Например, вы можете использовать его для проверки POST запроса.
В ответе вы увидите, что сервер получил данные вашего запроса и заголовки по мере их отправки. предоставляет вам эту информацию в форме .
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
Вызов исключений
Мы можем использовать ключевое слово raise, чтобы генерировать исключение из нашего кода. Некоторые из возможных сценариев:
- Ошибка проверки входных параметров функции;
- Поймать исключение и затем выбросить собственное.
class ValidationError(Exception): pass def divide(x, y): try: if type(x) is not int: raise TypeError("Unsupported type") if type(y) is not int: raise TypeError("Unsupported type") except TypeError as e: print(e) raise ValidationError("Invalid type of arguments") if y is 0: raise ValidationError("We can't divide by 0.") try: divide(10, 0) except ValidationError as ve: print(ve) try: divide(10, "5") except ValidationError as ve: print(ve)
Вывод:
We can't divide by 0. Unsupported type Invalid type of arguments
Выявление определенных исключений
В приведенном выше примере мы не упомянули какое-либо конкретное исключение в разделе except.
Это не очень хорошая практика программирования, поскольку она перехватывает все исключения и обрабатывает все случаи одинаково. Мы можем указать, какие исключения должно перехватывать предложение except.
Предложение try может иметь любое количество предложений except для обработки различных исключений, однако только одно будет выполнено в случае возникновения исключения.
Мы можем использовать кортеж значений, чтобы указать несколько исключений в предложении except. Вот пример псевдокода.
try: # do something pass except ValueError: # handle ValueError exception pass except (TypeError, ZeroDivisionError): # handle multiple exceptions # TypeError and ZeroDivisionError pass except: # handle all other exceptions pass
5.1. 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.
Catching Exceptions in Python
In Python, exceptions can be handled using a statement.
The critical operation which can raise an exception is placed inside the clause. The code that handles the exceptions is written in the clause.
We can thus choose what operations to perform once we have caught the exception. Here is a simple example.
Output
The entry is a Oops! <class 'ValueError'> occurred. Next entry. The entry is 0 Oops! <class 'ZeroDivisionError'> occured. Next entry. The entry is 2 The reciprocal of 2 is 0.5
In this program, we loop through the values of the randomList list. As previously mentioned, the portion that can cause an exception is placed inside the block.
If no exception occurs, the block is skipped and normal flow continues(for last value). But if any exception occurs, it is caught by the block (first and second values).
Here, we print the name of the exception using the function inside module. We can see that causes and causes .
Since every exception in Python inherits from the base class, we can also perform the above task in the following way:
This program has the same output as the above program.
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.
Python Exception Handling Best Practices
- Always try to handle the exception in the code to avoid abnormal termination of the program.
- When creating a custom exception class, suffix its name with “Error”.
- If the except clauses have the same code, try to catch multiple exceptions in a single except block.
- Use finally block to close heavy resources and remove heavy objects.
- Use else block to log successful execution of the code, send notifications, etc.
- Avoid bare except clause as much as possible. If you don’t know about the exceptions, then only use it.
- Create module-specific exception classes for specific scenarios.
- You can catch exceptions in an except block and then raise another exception that is more meaningful.
- Always raise exceptions with meaningful messages.
- Avoid nested try-except blocks because it reduces the readability of the code.
Советы
- Всегда пытайтесь обработать исключение в коде, чтобы избежать аварийного завершения программы.
- При создании настраиваемого класса исключения добавьте к его имени суффикс «Error».
- Если в предложениях except одинаковый код, попробуйте перехватить несколько исключений в одном блоке except.
- Используйте блок finally, чтобы закрыть тяжелые ресурсы.
- Используйте блок else для регистрации успешного выполнения кода, отправки уведомлений и т. д.
- По возможности избегайте голых исключений.
- Создавайте классы исключений для конкретных модулей для конкретных сценариев.
- Вы можете перехватить исключения в блоке except, а затем вызвать другое, которое будет более значимым.
- Всегда вызывайте с осмысленными сообщениями.
- Избегайте вложенных блоков try-except, потому что это снижает читаемость кода.
Customizing Exception Classes
We can further customize this class to accept other arguments as per our needs.
To learn about customizing the Exception classes, you need to have the basic knowledge of Object-Oriented programming.
Visit Python Object Oriented Programming to start learning about Object-Oriented programming in Python.
Let’s look at one example:
Output
Enter salary amount: 2000 Traceback (most recent call last): File "<string>", line 17, in <module> raise SalaryNotInRangeError(salary) __main__.SalaryNotInRangeError: Salary is not in (5000, 15000) range
Here, we have overridden the constructor of the class to accept our own custom arguments and . Then, the constructor of the parent class is called manually with the argument using .
The custom attribute is defined to be used later.
The inherited method of the class is then used to display the corresponding message when is raised.
We can also customize the method itself by overriding it.
Output
Enter salary amount: 2000 Traceback (most recent call last): File "/home/bsoyuj/Desktop/Untitled-1.py", line 20, in <module> raise SalaryNotInRangeError(salary) __main__.SalaryNotInRangeError: 2000 -> Salary is not in (5000, 15000) range
To learn more about how you can handle exceptions in Python, visit Python Exception 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.
5.4. Exception hierarchy¶
The class hierarchy for built-in exceptions is:
BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception +-- StopIteration +-- StopAsyncIteration +-- ArithmeticError | +-- FloatingPointError | +-- OverflowError | +-- ZeroDivisionError +-- AssertionError +-- AttributeError +-- BufferError +-- EOFError +-- ImportError | +-- ModuleNotFoundError +-- LookupError | +-- IndexError | +-- KeyError +-- MemoryError +-- NameError | +-- UnboundLocalError +-- OSError | +-- BlockingIOError | +-- ChildProcessError | +-- ConnectionError | | +-- BrokenPipeError | | +-- ConnectionAbortedError | | +-- ConnectionRefusedError | | +-- ConnectionResetError | +-- FileExistsError | +-- FileNotFoundError | +-- InterruptedError | +-- IsADirectoryError | +-- NotADirectoryError | +-- PermissionError | +-- ProcessLookupError | +-- TimeoutError +-- ReferenceError +-- RuntimeError | +-- NotImplementedError | +-- RecursionError +-- SyntaxError | +-- IndentationError | +-- TabError +-- SystemError +-- TypeError +-- ValueError | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning +-- ResourceWarning