{ "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(': 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: : 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(': 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\u001b[0m in \u001b[0;36m\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(': 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 .\n", "31.05.2021 16:54 ..\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 __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'\\n\\n\\n\\n \\n\\n Jupyter Notebook\\n \\n \\n \\n \\n \\n \\n \\n\\n \\n \\n\\n\\n \\n \\n \\n \\n \\n \\n \\n\\n \\n \\n\\n\\n\\n\\n\\n\\n\\n
\\n
\\n \\n\\n \\n \\n \\n \\n \\n \\n\\n\\n \\n \\n
\\n
\\n\\n \\n \\n
\\n\\n
\\n\\n\\n
\\n\\n \\n \\n
\\n
\\n
\\n
\\n
\\n
\\n \\n \\n \\n \\n \\n \\n
\\n
\\n
\\n
\\n
\\n
\\n \\n \\n \\n \\n
\\n

\\n Token authentication is enabled\\n

\\n

\\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 \\n enable a password.\\n

\\n

\\n The command:\\n

jupyter notebook list
\\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

\\n
Currently running servers:\\nhttp://localhost:8888/?token=c8de56fa... :: /Users/you/notebooks\\n
\\n

\\n or you can paste just the token value into the password field on this\\n page.\\n

\\n

\\n See\\n \\n the documentation on how to enable a password\\n \\n in place of token authentication,\\n if you would like to avoid dealing with random tokens.\\n

\\n

\\n Cookies are required for authenticated access to notebooks.\\n

\\n \\n

Setup a Password

\\n

You can also setup a password by entering your token and a new password\\n on the fields below:

\\n
\\n \\n
\\n \\n \\n
\\n
\\n \\n \\n
\\n
\\n \\n
\\n
\\n \\n\\n
\\n \\n \\n
\\n\\n\\n
\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n'" ] }, { "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 }