{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "06e0f3f7",
   "metadata": {},
   "source": [
    "# Исключения в requests #"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ced6c366",
   "metadata": {},
   "source": [
    "На предыдущих лекциях, когда мы говорили об исключениях, мы в основном использовали примеры работы с исключениями стандартной библиотеки Python. Однако существуют так называемые пользовательские исключения, и сегодня мы разберем пример работы с пользовательскими исключениями. И посмотрим, как они устроены и объявлены в библиотеке `requests`.\n",
    "\n",
    "Нам необходимо написать программу, которая на вход получает некий адрес в Интернете, выполняет скачивание содержимой странички по этому адресу и выводит на стандартный вывод содержимое этой странички."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "c7bc44ff",
   "metadata": {},
   "outputs": [
    {
     "ename": "ConnectionError",
     "evalue": "HTTPSConnectionPool(host='github-not-found.com', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x057BC328>: Failed to establish a new connection: [Errno 11004] getaddrinfo failed'))",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mgaierror\u001b[0m                                  Traceback (most recent call last)",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\connection.py\u001b[0m in \u001b[0;36m_new_conn\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    168\u001b[0m         \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 169\u001b[1;33m             conn = connection.create_connection(\n\u001b[0m\u001b[0;32m    170\u001b[0m                 \u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_dns_host\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mport\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mextra_kw\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\util\\connection.py\u001b[0m in \u001b[0;36mcreate_connection\u001b[1;34m(address, timeout, source_address, socket_options)\u001b[0m\n\u001b[0;32m     72\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 73\u001b[1;33m     \u001b[1;32mfor\u001b[0m \u001b[0mres\u001b[0m \u001b[1;32min\u001b[0m \u001b[0msocket\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetaddrinfo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mport\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfamily\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msocket\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mSOCK_STREAM\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[0m\u001b[0;32m     74\u001b[0m         \u001b[0maf\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msocktype\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mproto\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcanonname\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msa\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mres\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\socket.py\u001b[0m in \u001b[0;36mgetaddrinfo\u001b[1;34m(host, port, family, type, proto, flags)\u001b[0m\n\u001b[0;32m    917\u001b[0m     \u001b[0maddrlist\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--> 918\u001b[1;33m     \u001b[1;32mfor\u001b[0m \u001b[0mres\u001b[0m \u001b[1;32min\u001b[0m \u001b[0m_socket\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetaddrinfo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhost\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mport\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfamily\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mproto\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mflags\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[0m\u001b[0;32m    919\u001b[0m         \u001b[0maf\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msocktype\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mproto\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcanonname\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msa\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mres\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mgaierror\u001b[0m: [Errno 11004] getaddrinfo failed",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[1;31mNewConnectionError\u001b[0m                        Traceback (most recent call last)",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\connectionpool.py\u001b[0m in \u001b[0;36murlopen\u001b[1;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[0;32m    698\u001b[0m             \u001b[1;31m# Make the request on the httplib connection object.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 699\u001b[1;33m             httplib_response = self._make_request(\n\u001b[0m\u001b[0;32m    700\u001b[0m                 \u001b[0mconn\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\connectionpool.py\u001b[0m in \u001b[0;36m_make_request\u001b[1;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[0;32m    381\u001b[0m         \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 382\u001b[1;33m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_validate_conn\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mconn\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    383\u001b[0m         \u001b[1;32mexcept\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mSocketTimeout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mBaseSSLError\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\connectionpool.py\u001b[0m in \u001b[0;36m_validate_conn\u001b[1;34m(self, conn)\u001b[0m\n\u001b[0;32m   1009\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"sock\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m  \u001b[1;31m# AppEngine might not have  `.sock`\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1010\u001b[1;33m             \u001b[0mconn\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mconnect\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[0m\u001b[0;32m   1011\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\connection.py\u001b[0m in \u001b[0;36mconnect\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    352\u001b[0m         \u001b[1;31m# Add certificate verification\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 353\u001b[1;33m         \u001b[0mconn\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_new_conn\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[0m\u001b[0;32m    354\u001b[0m         \u001b[0mhostname\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhost\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\connection.py\u001b[0m in \u001b[0;36m_new_conn\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    180\u001b[0m         \u001b[1;32mexcept\u001b[0m \u001b[0mSocketError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 181\u001b[1;33m             raise NewConnectionError(\n\u001b[0m\u001b[0;32m    182\u001b[0m                 \u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"Failed to establish a new connection: %s\"\u001b[0m \u001b[1;33m%\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNewConnectionError\u001b[0m: <urllib3.connection.HTTPSConnection object at 0x057BC328>: Failed to establish a new connection: [Errno 11004] getaddrinfo failed",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[1;31mMaxRetryError\u001b[0m                             Traceback (most recent call last)",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\adapters.py\u001b[0m in \u001b[0;36msend\u001b[1;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[0;32m    438\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mchunked\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 439\u001b[1;33m                 resp = conn.urlopen(\n\u001b[0m\u001b[0;32m    440\u001b[0m                     \u001b[0mmethod\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmethod\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\connectionpool.py\u001b[0m in \u001b[0;36murlopen\u001b[1;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[0;32m    754\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 755\u001b[1;33m             retries = retries.increment(\n\u001b[0m\u001b[0;32m    756\u001b[0m                 \u001b[0mmethod\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0murl\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merror\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0me\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0m_pool\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0m_stacktrace\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0msys\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mexc_info\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\urllib3\\util\\retry.py\u001b[0m in \u001b[0;36mincrement\u001b[1;34m(self, method, url, response, error, _pool, _stacktrace)\u001b[0m\n\u001b[0;32m    573\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mnew_retry\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mis_exhausted\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--> 574\u001b[1;33m             \u001b[1;32mraise\u001b[0m \u001b[0mMaxRetryError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0m_pool\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0murl\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merror\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mResponseError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcause\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[0m\u001b[0;32m    575\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mMaxRetryError\u001b[0m: HTTPSConnectionPool(host='github-not-found.com', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x057BC328>: Failed to establish a new connection: [Errno 11004] getaddrinfo failed'))",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[1;31mConnectionError\u001b[0m                           Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-6-db0c1d5a7886>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mrequests\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mresponse\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mrequests\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"https://github-not-found.com\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\api.py\u001b[0m in \u001b[0;36mget\u001b[1;34m(url, params, **kwargs)\u001b[0m\n\u001b[0;32m     74\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     75\u001b[0m     \u001b[0mkwargs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msetdefault\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'allow_redirects'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 76\u001b[1;33m     \u001b[1;32mreturn\u001b[0m \u001b[0mrequest\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'get'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0murl\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mparams\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\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     77\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     78\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\api.py\u001b[0m in \u001b[0;36mrequest\u001b[1;34m(method, url, **kwargs)\u001b[0m\n\u001b[0;32m     59\u001b[0m     \u001b[1;31m# cases, and look like a memory leak in others.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     60\u001b[0m     \u001b[1;32mwith\u001b[0m \u001b[0msessions\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mSession\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0msession\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 61\u001b[1;33m         \u001b[1;32mreturn\u001b[0m \u001b[0msession\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mmethod\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0murl\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0murl\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\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     62\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     63\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\sessions.py\u001b[0m in \u001b[0;36mrequest\u001b[1;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[0;32m    540\u001b[0m         }\n\u001b[0;32m    541\u001b[0m         \u001b[0msend_kwargs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mupdate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msettings\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 542\u001b[1;33m         \u001b[0mresp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mprep\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0msend_kwargs\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    543\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    544\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[0mresp\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\sessions.py\u001b[0m in \u001b[0;36msend\u001b[1;34m(self, request, **kwargs)\u001b[0m\n\u001b[0;32m    653\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    654\u001b[0m         \u001b[1;31m# Send the request\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 655\u001b[1;33m         \u001b[0mr\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0madapter\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\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    656\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    657\u001b[0m         \u001b[1;31m# Total elapsed time of the request (approximately)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\adapters.py\u001b[0m in \u001b[0;36msend\u001b[1;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[0;32m    514\u001b[0m                 \u001b[1;32mraise\u001b[0m \u001b[0mSSLError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0me\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mrequest\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    515\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 516\u001b[1;33m             \u001b[1;32mraise\u001b[0m \u001b[0mConnectionError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0me\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mrequest\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mrequest\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    517\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    518\u001b[0m         \u001b[1;32mexcept\u001b[0m \u001b[0mClosedPoolError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mConnectionError\u001b[0m: HTTPSConnectionPool(host='github-not-found.com', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x057BC328>: Failed to establish a new connection: [Errno 11004] getaddrinfo failed'))"
     ]
    }
   ],
   "source": [
    "import requests\n",
    "\n",
    "response = requests.get(\"https://github-not-found.com\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01eea10e",
   "metadata": {},
   "source": [
    "Эта программа должна обрабатывать все исключения, которые возникают в процессе ее работы, и обрабатывать эти исключения соответствующим образом.\n",
    "\n",
    "Давайте для начала посмотрим, какие исключения существуют в библиотеке `requests`. Я уже установил виртуальное окружение, установил саму библиотеку `requests`. Вы уже знаете, как это делать. Давайте запустим интерпретатор, выполним импорт библиотеки, и посмотрим, где она находится в нашей системе."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "44e3584a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\__init__.py\n"
     ]
    }
   ],
   "source": [
    "import inspect\n",
    "import requests\n",
    "\n",
    "\n",
    "print(inspect.getfile(requests))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "eb3b69be",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\__init__.py\n"
     ]
    }
   ],
   "source": [
    "print(requests.__file__)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2615aff2",
   "metadata": {},
   "source": [
    "Итак, у нас получилось. Давайте скопируем в буфер обмена этот путь. И обратимся к специальному файлу, который называется `exceptions.py`. На экране мы видим содержимое файла `exceptions.py`, библиотеки `requests`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8dcc499a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " ’®¬ ў гбва®©бвўҐ C ­Ґ Ё¬ҐҐв ¬ҐвЄЁ.\n",
      " ‘ҐаЁ©­л© ­®¬Ґа в®¬ : 581B-1E7B\n",
      "\n",
      " ‘®¤Ґа¦Ё¬®Ґ Ї ЇЄЁ C:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\n",
      "\n",
      "31.05.2021  16:54    <DIR>          .\n",
      "31.05.2021  16:54    <DIR>          ..\n",
      "18.12.2020  02:44            21я344 adapters.py\n",
      "18.12.2020  02:44             6я496 api.py\n",
      "18.12.2020  02:44            10я207 auth.py\n",
      "18.12.2020  02:44               453 certs.py\n",
      "18.12.2020  02:44             1я782 compat.py\n",
      "18.12.2020  02:44            18я430 cookies.py\n",
      "18.12.2020  02:44             3я161 exceptions.py\n",
      "18.12.2020  02:44             3я515 help.py\n",
      "18.12.2020  02:44               757 hooks.py\n",
      "18.12.2020  02:44            34я308 models.py\n",
      "18.12.2020  02:44               542 packages.py\n",
      "18.12.2020  02:44            30я137 sessions.py\n",
      "18.12.2020  02:44             4я188 status_codes.py\n",
      "18.12.2020  02:44             3я005 structures.py\n",
      "18.12.2020  02:44            30я529 utils.py\n",
      "18.12.2020  02:44             1я096 _internal_utils.py\n",
      "18.12.2020  02:44             4я141 __init__.py\n",
      "31.05.2021  16:56    <DIR>          __pycache__\n",
      "18.12.2020  02:44               441 __version__.py\n",
      "              18 д ©«®ў        174я532 Ў ©в\n",
      "               3 Ї Ї®Є  42я176я192я512 Ў ©в бў®Ў®¤­®\n"
     ]
    }
   ],
   "source": [
    "! dir C:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3695b64f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# -*- coding: utf-8 -*-\n",
      "\n",
      "\"\"\"\n",
      "requests.exceptions\n",
      "~~~~~~~~~~~~~~~~~~~\n",
      "\n",
      "This module contains the set of Requests' exceptions.\n",
      "\"\"\"\n",
      "from urllib3.exceptions import HTTPError as BaseHTTPError\n",
      "\n",
      "\n",
      "class RequestException(IOError):\n",
      "    \"\"\"There was an ambiguous exception that occurred while handling your\n",
      "    request.\n",
      "    \"\"\"\n",
      "\n",
      "    def __init__(self, *args, **kwargs):\n",
      "        \"\"\"Initialize RequestException with `request` and `response` objects.\"\"\"\n",
      "        response = kwargs.pop('response', None)\n",
      "        self.response = response\n",
      "        self.request = kwargs.pop('request', None)\n",
      "        if (response is not None and not self.request and\n",
      "                hasattr(response, 'request')):\n",
      "            self.request = self.response.request\n",
      "        super(RequestException, self).__init__(*args, **kwargs)\n",
      "\n",
      "\n",
      "class HTTPError(RequestException):\n",
      "    \"\"\"An HTTP error occurred.\"\"\"\n",
      "\n",
      "\n",
      "class ConnectionError(RequestException):\n",
      "    \"\"\"A Connection error occurred.\"\"\"\n",
      "\n",
      "\n",
      "class ProxyError(ConnectionError):\n",
      "    \"\"\"A proxy error occurred.\"\"\"\n",
      "\n",
      "\n",
      "class SSLError(ConnectionError):\n",
      "    \"\"\"An SSL error occurred.\"\"\"\n",
      "\n",
      "\n",
      "class Timeout(RequestException):\n",
      "    \"\"\"The request timed out.\n",
      "\n",
      "    Catching this error will catch both\n",
      "    :exc:`~requests.exceptions.ConnectTimeout` and\n",
      "    :exc:`~requests.exceptions.ReadTimeout` errors.\n",
      "    \"\"\"\n",
      "\n",
      "\n",
      "class ConnectTimeout(ConnectionError, Timeout):\n",
      "    \"\"\"The request timed out while trying to connect to the remote server.\n",
      "\n",
      "    Requests that produced this error are safe to retry.\n",
      "    \"\"\"\n",
      "\n",
      "\n",
      "class ReadTimeout(Timeout):\n",
      "    \"\"\"The server did not send any data in the allotted amount of time.\"\"\"\n",
      "\n",
      "\n",
      "class URLRequired(RequestException):\n",
      "    \"\"\"A valid URL is required to make a request.\"\"\"\n",
      "\n",
      "\n",
      "class TooManyRedirects(RequestException):\n",
      "    \"\"\"Too many redirects.\"\"\"\n",
      "\n",
      "\n",
      "class MissingSchema(RequestException, ValueError):\n",
      "    \"\"\"The URL schema (e.g. http or https) is missing.\"\"\"\n",
      "\n",
      "\n",
      "class InvalidSchema(RequestException, ValueError):\n",
      "    \"\"\"See defaults.py for valid schemas.\"\"\"\n",
      "\n",
      "\n",
      "class InvalidURL(RequestException, ValueError):\n",
      "    \"\"\"The URL provided was somehow invalid.\"\"\"\n",
      "\n",
      "\n",
      "class InvalidHeader(RequestException, ValueError):\n",
      "    \"\"\"The header value provided was somehow invalid.\"\"\"\n",
      "\n",
      "\n",
      "class InvalidProxyURL(InvalidURL):\n",
      "    \"\"\"The proxy URL provided is invalid.\"\"\"\n",
      "\n",
      "\n",
      "class ChunkedEncodingError(RequestException):\n",
      "    \"\"\"The server declared chunked encoding but sent an invalid chunk.\"\"\"\n",
      "\n",
      "\n",
      "class ContentDecodingError(RequestException, BaseHTTPError):\n",
      "    \"\"\"Failed to decode response content.\"\"\"\n",
      "\n",
      "\n",
      "class StreamConsumedError(RequestException, TypeError):\n",
      "    \"\"\"The content for this response was already consumed.\"\"\"\n",
      "\n",
      "\n",
      "class RetryError(RequestException):\n",
      "    \"\"\"Custom retries logic failed\"\"\"\n",
      "\n",
      "\n",
      "class UnrewindableBodyError(RequestException):\n",
      "    \"\"\"Requests encountered an error when trying to rewind a body.\"\"\"\n",
      "\n",
      "# Warnings\n",
      "\n",
      "\n",
      "class RequestsWarning(Warning):\n",
      "    \"\"\"Base warning for Requests.\"\"\"\n",
      "\n",
      "\n",
      "class FileModeWarning(RequestsWarning, DeprecationWarning):\n",
      "    \"\"\"A file was opened in text mode, but Requests determined its binary length.\"\"\"\n",
      "\n",
      "\n",
      "class RequestsDependencyWarning(RequestsWarning):\n",
      "    \"\"\"An imported dependency doesn't match the expected version range.\"\"\"\n"
     ]
    }
   ],
   "source": [
    "! type C:\\ProgramData\\Anaconda3\\lib\\site-packages\\requests\\exceptions.py"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "770b2e7a",
   "metadata": {},
   "source": [
    "Давайте обратим внимание на исключения, которые в нем перечислены. Исключение `RequestException` является базовым классом для всех остальных исключений. В целом мы можем отлавливать именно это исключение и реагировать на ошибку работы этой библиотеки. Также существуют и другие исключения. Например, исключение `HTTPError`. Оно может генерироваться в случае, если нам пришел ответ, и его статус не равен `200 ОК`. Также различные исключения вида `ConnectionError` или `TimeoutError` могут возникать при проблемах с соединением по хосту, который указан в адресе.\n",
    "\n",
    "Итак, давайте начнем писать саму программу. Нам понадобится модуль `sys`, импортируем его. Также нам понадобится библиотека `requests`. Давайте получим адрес при помощи библиотеки `sys`. И попробуем скачать содержимое по этому адресу. После того, как мы скачали ответ, мы можем напечатать его. Давайте попробуем выполнить нашу программу."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b074f2ac",
   "metadata": {},
   "source": [
    "```python\n",
    "import sys\n",
    "import requests\n",
    "\n",
    "url = sys.argv[1]\n",
    "\n",
    "response = requests.get(url)\n",
    "\n",
    "print(response.content)\n",
    "```\n",
    "\n",
    "Запускаем ее при помощи интерпретатора, указываем адрес. Пусть это будет `python.net`. Итак, у нас получилось скачать содержимое по этому адресу и вывести на экран."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "c466a76c",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b'<!DOCTYPE HTML>\\n<html>\\n\\n<head>\\n    <meta charset=\"utf-8\">\\n\\n    <title>Jupyter Notebook</title>\\n    <link id=\"favicon\" rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/static/base/images/favicon.ico?v=50afa725b5de8b00030139d09b38620224d4e7dba47c07ef0e86d4643f30c9bfe6bb7e1a4a1c561aa32834480909a4b6fe7cd1e17f7159330b6b5914bf45a880\">\\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\\n    <link rel=\"stylesheet\" href=\"/static/components/jquery-ui/themes/smoothness/jquery-ui.min.css?v=fb45616eef2c454960f91fcd2a04efeda84cfacccf0c5d741ba2793dc1dbd6d3ab01aaae6485222945774c7d7a9a2e9fb87e0d8ef1ea96893aa6906147a371bb\" type=\"text/css\" />\\n    <link rel=\"stylesheet\" href=\"/static/components/jquery-typeahead/dist/jquery.typeahead.min.css?v=5edf53bf6bb9c3b1ddafd8594825a7e2ed621f19423e569c985162742f63911c09eba2c529f8fb47aebf27fafdfe287d563347f58c1126b278189a18871b6a9a\" type=\"text/css\" />\\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\\n    \\n    \\n\\n    <link rel=\"stylesheet\" href=\"/static/style/style.min.css?v=56dfd556850eb17b7998c6828467598a322b41593edc758739c66cb2c3fea98f23d0dd8bf8b9b0f5d67bb976a50e4c34f789fe640cbb440fa089e1bf5ec170bd\" type=\"text/css\"/>\\n    \\n<link rel=\"stylesheet\" href=\"/static/auth/css/override.css?v=7d24c52c4d63c7ed3ca286c051f232acd6a5ee3ed2aa32f56bea22ef20a2e3d184a638aad5602a39e8d5ef9a66ed93fdbaf80cf979948a947bab117618bd6486\" type=\"text/css\" />\\n\\n    <link rel=\"stylesheet\" href=\"/custom/custom.css\" type=\"text/css\" />\\n    <script src=\"/static/components/es6-promise/promise.min.js?v=bea335d74136a63ae1b5130f5ac9a50c6256a5f435e6e09fef599491a84d834a8b0f011ca3eaaca3b4ab6a2da2d3e1191567a2f171e60da1d10e5b9d52f84184\" type=\"text/javascript\" charset=\"utf-8\"></script>\\n    <script src=\"/static/components/react/react.production.min.js?v=9a0aaf84a316c8bedd6c2ff7d5b5e0a13f8f84ec02442346cba0b842c6c81a6bf6176e64f3675c2ebf357cb5bb048e0b527bd39377c95681d22468da3d5de735\" type=\"text/javascript\"></script>\\n    <script src=\"/static/components/react/react-dom.production.min.js?v=6fc58c1c4736868ff84f57bd8b85f2bdb985993a9392718f3b4af4bfa10fb4efba2b4ddd68644bd2a8daf0619a3844944c9c43f8528364a1aa6fc01ec1b8ae84\" type=\"text/javascript\"></script>\\n    <script src=\"/static/components/create-react-class/index.js?v=894ad57246e682b4cfbe7cd5e408dcd6b38d06af4de4f3425991e2676fdc2ef1732cbd19903104198878ae77de12a1996de3e7da3a467fb226bdda8f4618faec\" type=\"text/javascript\"></script>\\n    <script src=\"/static/components/requirejs/require.js?v=d37b48bb2137faa0ab98157e240c084dd5b1b5e74911723aa1d1f04c928c2a03dedf922d049e4815f7e5a369faa2e6b6a1000aae958b7953b5cc60411154f593\" type=\"text/javascript\" charset=\"utf-8\"></script>\\n    <script>\\n      require.config({\\n          \\n          urlArgs: \"v=20210615093238\",\\n          \\n          baseUrl: \\'/static/\\',\\n          paths: {\\n            \\'auth/js/main\\': \\'auth/js/main.min\\',\\n            custom : \\'/custom\\',\\n            nbextensions : \\'/nbextensions\\',\\n            kernelspecs : \\'/kernelspecs\\',\\n            underscore : \\'components/underscore/underscore-min\\',\\n            backbone : \\'components/backbone/backbone-min\\',\\n            jed: \\'components/jed/jed\\',\\n            jquery: \\'components/jquery/jquery.min\\',\\n            json: \\'components/requirejs-plugins/src/json\\',\\n            text: \\'components/requirejs-text/text\\',\\n            bootstrap: \\'components/bootstrap/dist/js/bootstrap.min\\',\\n            bootstraptour: \\'components/bootstrap-tour/build/js/bootstrap-tour.min\\',\\n            \\'jquery-ui\\': \\'components/jquery-ui/jquery-ui.min\\',\\n            moment: \\'components/moment/min/moment-with-locales\\',\\n            codemirror: \\'components/codemirror\\',\\n            termjs: \\'components/xterm.js/xterm\\',\\n            typeahead: \\'components/jquery-typeahead/dist/jquery.typeahead.min\\',\\n          },\\n          map: { // for backward compatibility\\n              \"*\": {\\n                  \"jqueryui\": \"jquery-ui\",\\n              }\\n          },\\n          shim: {\\n            typeahead: {\\n              deps: [\"jquery\"],\\n              exports: \"typeahead\"\\n            },\\n            underscore: {\\n              exports: \\'_\\'\\n            },\\n            backbone: {\\n              deps: [\"underscore\", \"jquery\"],\\n              exports: \"Backbone\"\\n            },\\n            bootstrap: {\\n              deps: [\"jquery\"],\\n              exports: \"bootstrap\"\\n            },\\n            bootstraptour: {\\n              deps: [\"bootstrap\"],\\n              exports: \"Tour\"\\n            },\\n            \"jquery-ui\": {\\n              deps: [\"jquery\"],\\n              exports: \"$\"\\n            }\\n          },\\n          waitSeconds: 30,\\n      });\\n\\n      require.config({\\n          map: {\\n              \\'*\\':{\\n                \\'contents\\': \\'services/contents\\',\\n              }\\n          }\\n      });\\n\\n      // error-catching custom.js shim.\\n      define(\"custom\", function (require, exports, module) {\\n          try {\\n              var custom = require(\\'custom/custom\\');\\n              console.debug(\\'loaded custom.js\\');\\n              return custom;\\n          } catch (e) {\\n              console.error(\"error loading custom.js\", e);\\n              return {};\\n          }\\n      })\\n\\n    document.nbjs_translations = {\"domain\": \"nbjs\", \"locale_data\": {\"nbjs\": {\"\": {\"domain\": \"nbjs\"}}}};\\n    document.documentElement.lang = navigator.language.toLowerCase();\\n    </script>\\n\\n    \\n    \\n\\n</head>\\n\\n<body class=\"\"\\n \\n  \\n \\ndir=\"ltr\">\\n\\n<noscript>\\n    <div id=\\'noscript\\'>\\n      Jupyter Notebook requires JavaScript.<br>\\n      Please enable it to proceed. \\n  </div>\\n</noscript>\\n\\n<div id=\"header\" role=\"navigation\" aria-label=\"Top Menu\">\\n  <div id=\"header-container\" class=\"container\">\\n  <div id=\"ipython_notebook\" class=\"nav navbar-brand\"><a href=\"/tree\" title=\\'dashboard\\'>\\n      <img src=\\'/static/base/images/logo.png?v=a2a176ee3cee251ffddf5fa21fe8e43727a9e5f87a06f9c91ad7b776d9e9d3d5e0159c16cc188a3965e00375fb4bc336c16067c688f5040c0c2d4bfdb852a9e4\\' alt=\\'Jupyter Notebook\\'/>\\n  </a></div>\\n\\n  \\n  \\n  \\n  \\n  \\n  \\n\\n\\n  \\n  \\n  </div>\\n  <div class=\"header-bar\"></div>\\n\\n  \\n  \\n</div>\\n\\n<div id=\"site\">\\n\\n\\n<div id=\"ipython-main-app\" class=\"container\">\\n\\n    \\n    \\n    <div class=\"row\">\\n    <div class=\"navbar col-sm-8\">\\n      <div class=\"navbar-inner\">\\n        <div class=\"container\">\\n          <div class=\"center-nav\">\\n            <form action=\"/login?next=%2Ftree\" method=\"post\" class=\"navbar-form pull-left\">\\n              <input type=\"hidden\" name=\"_xsrf\" value=\"2|886c0a63|94fdd3feacfc4e01bf1b171a302301bf|1623738965\"/>\\n              \\n                <label for=\"password_input\"><strong>Password or token:</strong></label>\\n              \\n              <input type=\"password\" name=\"password\" id=\"password_input\" class=\"form-control\">\\n              <button type=\"submit\" class=\"btn btn-default\" id=\"login_submit\">Log in</button>\\n            </form>\\n          </div>\\n        </div>\\n      </div>\\n    </div>\\n    </div>\\n    \\n    \\n    \\n    \\n    <div class=\"col-sm-6 col-sm-offset-3 text-left rendered_html\">\\n      <h3>\\n        Token authentication is enabled\\n      </h3>\\n      <p>\\n        If no password has been configured, you need to open the notebook\\n        server with its login token in the URL, or paste it above.\\n        This requirement will be lifted if you\\n        <b><a href=\\'https://jupyter-notebook.readthedocs.io/en/stable/public_server.html\\'>\\n            enable a password</a></b>.\\n      </p>\\n      <p>\\n        The command:\\n        <pre>jupyter notebook list</pre>\\n        will show you the URLs of running servers with their tokens,\\n        which you can copy and paste into your browser. For example:\\n      </p>\\n      <pre>Currently running servers:\\nhttp://localhost:8888/?token=c8de56fa... :: /Users/you/notebooks\\n</pre>\\n      <p>\\n        or you can paste just the token value into the password field on this\\n        page.\\n      </p>\\n      <p>\\n        See\\n        <b><a\\n         href=\\'https://jupyter-notebook.readthedocs.io/en/stable/public_server.html\\'>\\n                the documentation on how to enable a password</a>\\n        </b>\\n        in place of token authentication,\\n        if you would like to avoid dealing with random tokens.\\n      </p>\\n      <p>\\n        Cookies are required for authenticated access to notebooks.\\n      </p>\\n      \\n        <h3>Setup a Password</h3>\\n        <p> You can also setup a password by entering your token and a new password\\n        on the fields below:</p>\\n        <form action=\"/login?next=%2Ftree\" method=\"post\" class=\"\">\\n                <input type=\"hidden\" name=\"_xsrf\" value=\"2|886c0a63|94fdd3feacfc4e01bf1b171a302301bf|1623738965\"/>\\n          <div class=\"form-group\">\\n            <label for=\"token_input\"><h4>Token</h4></label>\\n            <input type=\"password\" name=\"password\" id=\"token_input\" class=\"form-control\">\\n          </div>\\n          <div class=\"form-group\">\\n            <label for=\"new_password_input\"><h4>New Password</h4></label>\\n            <input type=\"password\" name=\"new_password\" id=\"new_password_input\" class=\"form-control\" required>\\n          </div>\\n          <div class=\"form-group\">\\n            <button type=\"submit\" class=\"btn btn-default\" id=\"login_new_pass_submit\">Log in and set new password</button>\\n          </div>\\n        </form>\\n      \\n\\n    </div>\\n    \\n    \\n</div>\\n\\n\\n</div>\\n\\n\\n\\n\\n\\n\\n\\n\\n<script type=\"text/javascript\">\\n  require([\"auth/js/main\"], function (auth) {\\n    auth.login_main();\\n  });\\n</script>\\n\\n\\n\\n<script type=\\'text/javascript\\'>\\n  function _remove_token_from_url() {\\n    if (window.location.search.length <= 1) {\\n      return;\\n    }\\n    var search_parameters = window.location.search.slice(1).split(\\'&\\');\\n    for (var i = 0; i < search_parameters.length; i++) {\\n      if (search_parameters[i].split(\\'=\\')[0] === \\'token\\') {\\n        // remote token from search parameters\\n        search_parameters.splice(i, 1);\\n        var new_search = \\'\\';\\n        if (search_parameters.length) {\\n          new_search = \\'?\\' + search_parameters.join(\\'&\\');\\n        }\\n        var new_url = window.location.origin + \\n                      window.location.pathname + \\n                      new_search + \\n                      window.location.hash;\\n        window.history.replaceState({}, \"\", new_url);\\n        return;\\n      }\\n    }\\n  }\\n  _remove_token_from_url();\\n</script>\\n</body>\\n\\n</html>'"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "! python wget.py http://localhost:8888"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e67e676e",
   "metadata": {},
   "source": [
    "Давайте теперь напишем обработчики исключений, которые могут возникать при работе с данной библиотекой.\n",
    "\n",
    "Во-первых, давайте зададим `timeout`. Пусть он будет равен 30-ти секундам. Если мы задаем `timeout`, и за эти 30 секунд мы не получаем ответа от сервера, то будет сгенерировано исключение `TimeoutError`. Давайте его обработаем. Для этого напишем `try/except`, `requests.Timeout`. Если мы получили `Timeout`, выведем соответствующее сообщение. И укажем `url`. Если же у нас исключение не произошло, мы можем использовать блок `else`. И в блоке `else` выводить содержимое нашего ответа.\n",
    "\n",
    "```python\n",
    "import sys\n",
    "import requests\n",
    "\n",
    "url = sys.argv[1]\n",
    "\n",
    "try:\n",
    "    response = requests.get(url, timeout=30)\n",
    "    \n",
    "except requests.Timeout:\n",
    "    print(\"Ошибка timeout, url:\", url)\n",
    "\n",
    "else:\n",
    "    print(response.content)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e95fa508",
   "metadata": {},
   "source": [
    "Но допустим, если мы ввели несуществующий адрес, и статус ответа не 200 ОК, нам тоже необходимо обработать такую ошибку. Сделать это можно следующим образом. Для начала необходимо сгенерировать исключение `HTTPError`. Делается это при помощи метода `raise_for_status`. И затем мы сможем отловить это исключение. Давайте выведем соответствующее сообщение об ошибке. Предположим, мы хотим также в сообщении об ошибке видеть `status code` нашего ответа. Можем сделать это. И сейчас я покажу, как это можно сделать. Если у нас произошло исключение вида `HTTPError`, то сам ответ доступен по атрибуту `response`. И мы можем обратиться к нему соответствующим образом. Нам нужен сам `status code`, он хранится в атрибуте `status_code`. Всё, теперь мы можем вывести его.\n",
    "\n",
    "```python\n",
    "import sys\n",
    "import requests\n",
    "\n",
    "url = sys.argv[1]\n",
    "\n",
    "try:\n",
    "    response = requests.get(url, timeout=30)\n",
    "    response.raise_for_status()\n",
    "    \n",
    "except requests.Timeout:\n",
    "    print(\"Ошибка timeout, url:\", url)\n",
    "\n",
    "except requests.HTTPError as err:\n",
    "    code = err.response.status_code\n",
    "    print(f\"Ошибка url: {url}, code: {code}\")\n",
    "    \n",
    "else:\n",
    "    print(response.content)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e250678",
   "metadata": {},
   "source": [
    "Также у нас могут возникать и другие исключения. Давайте обработаем и этот момент. Мы будем отлавливать базовый класс и выводить соответствующее сообщение. Вот так выглядит обработка исключений от библиотеки `requests`. Давайте попробуем запустить нашу программу. И посмотрим, как она работает. Давайте, например, обратимся к несуществующему адресу. Запускаем.\n",
    "\n",
    "```python\n",
    "import sys\n",
    "import requests\n",
    "\n",
    "url = sys.argv[1]\n",
    "\n",
    "try:\n",
    "    response = requests.get(url, timeout=30)\n",
    "    response.raise_for_status()\n",
    "    \n",
    "except requests.Timeout:\n",
    "    print(\"Ошибка timeout, url:\", url)\n",
    "\n",
    "except requests.HTTPError as err:\n",
    "    code = err.response.status_code\n",
    "    print(f\"Ошибка url: {url}, code: {code}\")\n",
    "\n",
    "except requests.RequestException:\n",
    "    print(\"Ошибка скачивания url:\", url)\n",
    "    \n",
    "else:\n",
    "    print(response.content)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "8660cd85",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ошибка url: http://localhost:8888/test, code: 404\n"
     ]
    }
   ],
   "source": [
    "! python wget.py http://localhost:8888/test"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37e905f6",
   "metadata": {},
   "source": [
    "Так видим соответствующее сообщение в нашем стандартном выводе. Также мы можем сгенерировать какое-то другое исключение. Давайте попробуем обратиться к несуществующему хосту."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "88c232ce",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ошибка скачивания url: https://google.com\n"
     ]
    }
   ],
   "source": [
    "! python wget.py https://google.com"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ed15ace",
   "metadata": {},
   "source": [
    "Итак, видим, что у нас соответствующее исключение было обработано нужным образом. Таким образом, мы написали программу, которая скачивает `url` и обрабатывает все нужные исключения, которые могут возникнуть при работе с библиотекой `requests`.\n",
    "\n",
    "Вы можете писать собственные исключения и делать это похожим образом, как это реализовано в этой библиотеке. Мы с вами поговорили про исключения. Про то, как устроены пользовательские исключения. И теперь вы можете использовать этот механизм для написания заданий по нашему курсу."
   ]
  }
 ],
 "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
}
