You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
30 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"id": "4b201c2f",
"metadata": {},
"source": [
"# Генерация исключений #"
]
},
{
"cell_type": "markdown",
"id": "249ae766",
"metadata": {},
"source": [
"На предыдущей лекции мы начали с вами свое знакомство с исключениями, и в этой лекции мы продолжим разбирать их работу и обсудим более подробно, как обрабатывать исключения, как получать доступ к объекту исключения, а также обсудим отдельные исключения вида `AssertionError` и вопросы производительности исключений."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "5677dc5b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2 No such file or directory\n"
]
}
],
"source": [
"try:\n",
" with open(\"/file/not/found\") as f:\n",
" content = f.read()\n",
" \n",
"except OSError as err:\n",
" print(err.errno, err.strerror)"
]
},
{
"cell_type": "markdown",
"id": "bba1230f",
"metadata": {},
"source": [
"Для того чтобы получить доступ к объекту исключений, нам необходимо воспользоваться конструкцией `except as err`. В данном примере, если будет сгенерировано исключение `OSError`, то сам объект исключений будет связан с переменной `err` и эта переменная `err` будет доступна в блоке `except`."
]
},
{
"cell_type": "markdown",
"id": "56767c12",
"metadata": {},
"source": [
"У каждого объекта типа исключений есть свои свойства, например, `errno` и `srterror` — это строковое описание ошибки и код ошибки. При помощи этих атрибутов можно получать доступ и обрабатывать исключения нужным вам образом. Очень часто используется атрибут `args` для доступа к атрибутам исключения."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "0c4d7d62",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"файл не существует /file/not/found\n"
]
}
],
"source": [
"import os.path\n",
"\n",
"filename = \"/file/not/found\"\n",
"\n",
"try:\n",
" if not os.path.exists(filename):\n",
" raise ValueError(\"файл не существует\", filename)\n",
" \n",
"except ValueError as err:\n",
" message, filename = err.args[0], err.args[1]\n",
" print(message, filename)"
]
},
{
"cell_type": "markdown",
"id": "e3e20202",
"metadata": {},
"source": [
"Предположим, мы проверили, что файл не существует, и сгенерировали исключение `ValueError`, передали туда строку и имя файла. Так вот, если мы в блоке `except` обратимся к объекту исключения, то у него будут доступен атрибут `args` — это список из наших параметров и можем делать с ними все, что захотим.\n",
"\n",
"Иногда нам может потребоваться стек вызовов при генерации исключения. Стек вызовов можно получить при помощи модуля `traceback` и вызвать метод `print_exc`. Давайте попробуем выполнить этот пример в консоли и посмотрим, что выведется на экран."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "21569499",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"None\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Traceback (most recent call last):\n",
" File \"<ipython-input-4-adc0be654a54>\", line 4, in <module>\n",
" with open(\"/file/not/found\") as f:\n",
"FileNotFoundError: [Errno 2] No such file or directory: '/file/not/found'\n"
]
}
],
"source": [
"import traceback\n",
"\n",
"try:\n",
" with open(\"/file/not/found\") as f:\n",
" content = f.read()\n",
"\n",
"except OSError as err:\n",
" trace = traceback.print_exc()\n",
" print(trace)"
]
},
{
"cell_type": "markdown",
"id": "06d47261",
"metadata": {},
"source": [
"Итак, у нас получилось распечатать стек вызовов. Иногда стек вызовов может вам помочь при разбирательстве причин, при которых возникло исключение. \n",
"\n",
"Для того чтобы сгенерировать, собственно, исключение, вам необходима инструкция `raise`. Для генерации исключения мы должны написать `raise` и указать класс исключения. Также можно указывать не только класс, но и объект исключения, и указывать ему дополнительные какие-то свойства. Как я уже говорил, к этим свойствам потом можно будет обратится через объект исключения при помощи атрибута `args`."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "b578c4de",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"введите число: w\n",
"некорректное значение!\n"
]
}
],
"source": [
"try:\n",
" raw = input(\"введите число: \")\n",
" if not raw.isdigit():\n",
" raise ValueError\n",
" \n",
"except ValueError:\n",
" print(\"некорректное значение!\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "28e93b13",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"введите число: w\n",
"некорректное значение! ('плохое число', 'w')\n"
]
}
],
"source": [
"try:\n",
" raw = input(\"введите число: \")\n",
" if not raw.isdigit():\n",
" raise ValueError(\"плохое число\", raw)\n",
" \n",
"except ValueError as err:\n",
" print(\"некорректное значение!\", err)"
]
},
{
"cell_type": "markdown",
"id": "531ad8cc",
"metadata": {},
"source": [
"В данном случае мы проверяем, что пользователь ввел не число и если так действительно произошло, то генерируем исключение и затем в блоке `except` обрабатываем его.\n",
"\n",
"Иногда может случиться так, что вы пишете какую-то функцию и отлавливаете исключения, но вы не знаете, что делать дальше с этим исключением. Например, вы можете просто вывести какую-то информацию на экран и делегировать обработку этого исключения другим функциям — тем, который вызвали вашу. Для этого нужно использовать инструкцию `raise` без параметров."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "0348d576",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"введите число: e\n",
"некорректное значение! ('плохое число', 'e')\n"
]
},
{
"ename": "ValueError",
"evalue": "('плохое число', 'e')",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-7-03e61a5d927e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mraw\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0minput\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"введите число: \"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mraw\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0misdigit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"плохое число\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mraw\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mValueError\u001b[0m: ('плохое число', 'e')"
]
}
],
"source": [
"try:\n",
" raw = input(\"введите число: \")\n",
" \n",
" if not raw.isdigit():\n",
" raise ValueError(\"плохое число\", raw)\n",
"\n",
"except ValueError as err:\n",
" print(\"некорректное значение!\", err)\n",
" # делегирование обработки исключения\n",
" raise"
]
},
{
"cell_type": "markdown",
"id": "75611c95",
"metadata": {},
"source": [
"В данном случае все происходит тоже самое, как в предыдущем примере, генерируются исключения, на экран выводится надпись \"Некорректное значение\", и при помощи инструкции `raise` мы делегируем исключение выше. Если мы попробуем исполнить код, то интерпретатор просто покажет на стандартный вывод информации об этом исключении и прекратит работу нашей программы. Если таких мест, в которых исключения делегируются, очень много, то иногда не понятно по последнему исключению, где именно оно возникло и для этого может использоваться конструкция `raise from Exception`. Давайте посмотрим, как отработает наша программа."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "fea7bab6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"введите число: d\n",
"ошибка: плохое число d\n"
]
},
{
"ename": "TypeError",
"evalue": "ошибка",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-8-23aebd9f3114>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mraw\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0misdigit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"плохое число\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mraw\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 6\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mValueError\u001b[0m: ('плохое число', 'd')",
"\nThe above exception was the direct cause of the following exception:\n",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-8-23aebd9f3114>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 8\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"ошибка:\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 9\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"ошибка\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m: ошибка"
]
}
],
"source": [
"try:\n",
" raw = input(\"введите число: \")\n",
" \n",
" if not raw.isdigit():\n",
" raise ValueError(\"плохое число\", raw)\n",
" \n",
"except ValueError as err:\n",
" print(\"ошибка:\", err.args[0], err.args[1])\n",
" raise TypeError(\"ошибка\") from err"
]
},
{
"cell_type": "markdown",
"id": "00db7b28",
"metadata": {},
"source": [
"Если мы сгенерируем одно исключение, отловим его в блоке `except`, и затем сгенерируем второе исключение `TypeError`, но укажем ему конструкцию `from err`. У нас получилось вызвать исключение и давайте внимательно посмотрим на `stack trace`, который произошел. Мы видим, что произошло исключение `ValueError` — это изначально которое мы сгенерировали. И дальше мы видим его `stack trace`, этого исключения. Дальше мы видим, что после этого исключения произошло второе исключение — `TypeError` и его `stack trace`. Таким образом, если мы будем использовать конструкцию `raise from Exception`, мы сможем отслеживать всю цепочку исключений, которая была сгенерирована."
]
},
{
"cell_type": "markdown",
"id": "c41f831b",
"metadata": {},
"source": [
"Говоря об исключениях, нельзя не затронуть инструкцию `assert`. Давайте поговорим, зачем она нужна. По умолчанию, если выполнить инструкцию `assert` с логическим выражением `True`, ничего не произойдет, но если попробовать выполнить инструкцию `assert` с логическим выражением, которое равно `False`, или \"ложь\", то будет сгенерировано исключение `AssertionError`."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "64bc3761",
"metadata": {},
"outputs": [],
"source": [
"assert True"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4c4c07fe",
"metadata": {
"scrolled": true
},
"outputs": [
{
"ename": "AssertionError",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-10-e99f91a18d62>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m: "
]
}
],
"source": [
"assert 1 == 0"
]
},
{
"cell_type": "markdown",
"id": "caeb02ab",
"metadata": {},
"source": [
"Также мы можем передать некую дополнительную строку, которая будет потом передана в сам объект `AssertionError`."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "381676b1",
"metadata": {},
"outputs": [
{
"ename": "AssertionError",
"evalue": "1 не равен 0",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-11-e2b654902c90>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"1 не равен 0\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m: 1 не равен 0"
]
}
],
"source": [
"assert 1 == 0, \"1 не равен 0\""
]
},
{
"cell_type": "markdown",
"id": "e799aaab",
"metadata": {},
"source": [
"Давайте разберем кейсы, в каких случаях может использоваться `AssertionError` и инструкция `assert`. \n",
"\n",
"Предположим, у нас есть функция, она называется `get_user_by_id`, она нам ищет некоего пользователя по численному идентификатору. Мы должны убедиться в том, что нам действительно передали число, что мы работаем с целым числом. Это можно сделать при помощи `assert` и функции `isinstance`, то есть мы проверяем, является ли входной параметр `id` целым числом. Если это не так, то будет сгенерирована `AssertionError`."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "33871e62",
"metadata": {},
"outputs": [
{
"ename": "AssertionError",
"evalue": "id должен быть целым числом",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-12-6bcefc7016e1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0m__name__\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m\"__main__\"\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 6\u001b[1;33m \u001b[0mget_user_by_id\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"foo\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-12-6bcefc7016e1>\u001b[0m in \u001b[0;36mget_user_by_id\u001b[1;34m(id)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mget_user_by_id\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mid\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mid\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"id должен быть целым числом\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"выполняем поиск\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0m__name__\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m\"__main__\"\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mAssertionError\u001b[0m: id должен быть целым числом"
]
}
],
"source": [
"def get_user_by_id(id):\n",
" assert isinstance(id, int), \"id должен быть целым числом\"\n",
" print(\"выполняем поиск\")\n",
"\n",
"if __name__ == \"__main__\":\n",
" get_user_by_id(\"foo\")"
]
},
{
"cell_type": "markdown",
"id": "5196f5e1",
"metadata": {},
"source": [
"Итак, у нас сгенерировалось исключение `AssertionError`. Дело в том, что такие исключения не нужно обрабатывать — эти исключения, они предназначены, скорее, для программистов. То есть при написании наших программ на этапе разработки мы должны видеть, что мы делаем что-то не так, то есть мы передали в функцию некорректное значение, и видим `AssertionError` — наша программа завершила свою работу. В таком случае мы должны как-то реагировать и изменять код нашей программы. Не нужно, например, обрабатывать пользовательский ввод и пытаться обработать исключение `AssetionError` блоком `try except`.\n",
"\n",
"Если у нас таких мест будет очень много, то это затронет и производительность нашей программы. Оказывается, можно отключить все инструкции `assert` при помощи флага `O`. Тогда `AssertionError`, инструкция не будет сгенерирована, потому что `assert` вызван не будет. Этим как раз отличаются эти исключения от обычных пользовательских исключений и исключений стандартной библиотеки. Давайте попробуем сделать это. Запустим с флагом `O` нашу программу."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "310942f0",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"выполняем поиск\n"
]
}
],
"source": [
"! python -O ex.py"
]
},
{
"cell_type": "markdown",
"id": "765e8f49",
"metadata": {},
"source": [
"Итак, мы видим, что наша функция отработала, исключение `AssertionError` не было сгенерировано.\n",
"\n",
"Давайте еще поговорим немного о производительности исключений. Несмотря на то, что механизм обработки исключений очень удобный и его очень хорошо использовать в своих программах, тем не менее этот механизм не бесплатен. \n",
"\n",
"Рассмотрим пример. У нас есть цикл, и в этом цикле мы обращаемся к несуществующему ключу словаря и каждый раз при этом обращении у нас генерируется исключение `KeyError`. Попробуем при помощи `timeit` замерить, сколько это займет — мы получим некую условную единицу, тысячу операций мы смогли выполнить."
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "6f59e6df",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"454 µs ± 9.97 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"my_dict = {\"foo\": 1}\n",
"\n",
"for _ in range(1000):\n",
" try:\n",
" my_dict[\"bar\"]\n",
" \n",
" except KeyError:\n",
" pass"
]
},
{
"cell_type": "markdown",
"id": "469eb46f",
"metadata": {},
"source": [
"Если мы попробуем реализовать ту же самую задачу, но без использования исключений, например, при помощи конструкции `in`, то есть мы проверяем, что у нас ключик `bar` находится в словаре, и только в этом случае тогда мы обращаемся по ключу к этому словарю. Давайте опять попробуем посмотреть на результаты работы `timeit` для этого примера — и мы видим, что результат отличается на порядок, а иногда он может отличаться и на несколько порядков."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "4c40a7cb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"67.3 µs ± 4.65 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"my_dict = {\"foo\": 1}\n",
"\n",
"for _ in range(1000):\n",
" if \"bar\" in my_dict:\n",
" _ = my_dict[\"bar\"]"
]
},
{
"cell_type": "markdown",
"id": "85daa3f9",
"metadata": {},
"source": [
"То есть хочу обратить ваше внимание на то, что исключения, особенно если они у вас генерируются в программе очень часто, возможно следует изменить код вашей программы и сделать так, чтобы она работала без исключений, потому, что это очень сильно влияет на производительность вашей итоговой Python программы.\n",
"\n",
"Итак, мы обсудили вопросы, которые касаются исключений, поговорили про доступ к объекту исключений, о том как генерируются исключения при помощи `raise`, также обсудили специальные исключения типа `AssertionError`, поговорили о вопросах производительности и нам осталось поговорить о работе с собственными исключениями. В целом работа с собственными исключениями никак не отличается от работы с исключениями стандартной библиотеки и мы попробуем в следующей лекции разобрать работу с собственными исключениями на конкретном примере работы с библиотекой `requests`."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}