image.png

Introduction

Why do we need Flask?

All types of web applications:

  1. Static web apps (sites)
  2. Dynamic web apps
  3. E-Commerce
  4. Portal Web App
  5. Helping web servers (eg Telegram bots) etc

Flask is a web framework. This means flask provides you with tools, libraries and technologies that allow you to build a web application.

Flask uses HTTP protocol.

HTTP is a resource-based application layer protocol. It defines the rules for communication between web clients (browsers) and web servers and follows a client-server model.

Http requests:

  1. GET
  2. POST
  3. PUT
  4. HEAD
  5. DELETE
  6. PATCH
  7. OPTIONS

The GET Method

GET is used to request data from a specified resource.

GET is one of the most common HTTP methods.

Note that the query string (name/value pairs) is sent in the URL of a GET request:

This is the request we have been using previously to get data from APIs

someurl.com/test?name1=value1&name2=value2

  1. GET requests can be cached
  2. GET requests remain in the browser history
  3. GET requests can be bookmarked
  4. GET requests should never be used when dealing with sensitive data
  5. GET requests have length restrictions
  6. GET requests are only used to request data (not modify)

The POST Method

POST is used to send data to a server to create/update a resource.

The data sent to the server with POST is stored in the request body of the HTTP request:

POST /test/demo_form.php HTTP/1.1

Host: someurl.com

name1=value1&name2=value2

POST is one of the most common HTTP methods.

  1. POST requests are never cached
  2. POST requests do not remain in the browser history
  3. POST requests cannot be bookmarked
  4. POST requests have no restrictions on data length

The PUT Method

PUT is used to send data to a server to create/update a resource.

The difference between POST and PUT is that PUT requests are idempotent. That is, calling the same PUT request multiple times will always produce the same result. In contrast, calling a POST request repeatedly have side effects of creating the same resource multiple times.

The HEAD Method

HEAD is almost identical to GET, but without the response body.

In other words, if GET /users returns a list of users, then HEAD /users will make the same request but will not return the list of users.

HEAD requests are useful for checking what a GET request will return before actually making a GET request - like before downloading a large file or response body.

The DELETE Method

The DELETE method deletes the specified resource.

The OPTIONS Method

The OPTIONS method describes the communication options for the target resource.

Using the requests module we have been making GET requests. We can do other requests like this, too

In [4]:
import requests
res = requests.get("https://api.stackexchange.com/2.3/search?order=desc&sort=activity&tagged=python&intitle=requests&site=stackoverflow")
res.text
Out[4]:
'{"items":[{"tags":["python","ssl","asynchronous","https","http-post"],"owner":{"account_id":5784332,"reputation":3238,"user_id":4564080,"user_type":"registered","accept_rate":67,"profile_image":"https://www.gravatar.com/avatar/83009ae032b72f3c1aa2bba01ab123e1?s=256&d=identicon&r=PG&f=1","display_name":"KOB","link":"https://stackoverflow.com/users/4564080/kob"},"is_answered":false,"view_count":6,"answer_count":0,"score":0,"last_activity_date":1639409179,"creation_date":1639408858,"last_edit_date":1639409179,"question_id":70336975,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70336975/same-tls-post-request-works-fine-with-requests-but-certificate-verification-fail","title":"Same TLS post request works fine with requests but certificate verification fails with aiohttp"},{"tags":["python","locking","threadpool","race-condition"],"owner":{"account_id":20484642,"reputation":5,"user_id":15032100,"user_type":"registered","profile_image":"https://i.stack.imgur.com/1kCTa.jpg?s=256&g=1","display_name":"Pascal Widmann","link":"https://stackoverflow.com/users/15032100/pascal-widmann"},"is_answered":false,"view_count":5,"answer_count":0,"score":0,"last_activity_date":1639406787,"creation_date":1639406787,"question_id":70336471,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70336471/queue-requests-to-write-instead-of-dismissing-them-in-a-thread-race-event","title":"Queue requests to write instead of dismissing them in a thread race event"},{"tags":["python","django","asynchronous","celery","gunicorn"],"owner":{"account_id":13879709,"reputation":1636,"user_id":10020360,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/6c3ffce233a93593ce4b4d246b54a998?s=256&d=identicon&r=PG&f=1","display_name":"PolarBear10","link":"https://stackoverflow.com/users/10020360/polarbear10"},"is_answered":false,"view_count":14,"answer_count":0,"score":0,"last_activity_date":1639400812,"creation_date":1639399397,"last_edit_date":1639400812,"question_id":70334875,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70334875/how-to-combine-celery-with-asyncio-to-handle-http-requests-asynchronously","title":"How to combine Celery with asyncio to handle HTTP requests asynchronously?"},{"tags":["python","bottle"],"owner":{"account_id":118702,"reputation":10332,"user_id":309917,"user_type":"registered","accept_rate":81,"profile_image":"https://www.gravatar.com/avatar/9078cfc8ee49095f0d6f33db12f099dd?s=256&d=identicon&r=PG","display_name":"neurino","link":"https://stackoverflow.com/users/309917/neurino"},"is_answered":true,"view_count":30,"accepted_answer_id":70316049,"answer_count":1,"score":1,"last_activity_date":1639397546,"creation_date":1638529323,"last_edit_date":1638531986,"question_id":70213267,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70213267/redirect-all-non-www-requests-to-www-in-bottle-py","title":"Redirect all non-www requests to www in bottle-py"},{"tags":["python","flask","dlib"],"owner":{"account_id":14274621,"reputation":49,"user_id":10311174,"user_type":"registered","profile_image":"https://lh6.googleusercontent.com/-M0GScdK5Lk8/AAAAAAAAAAI/AAAAAAAAs90/emlZpzkH8G4/photo.jpg?sz=256","display_name":"D Nunes","link":"https://stackoverflow.com/users/10311174/d-nunes"},"is_answered":false,"view_count":17,"answer_count":0,"score":-2,"last_activity_date":1639362347,"creation_date":1639359704,"last_edit_date":1639362347,"question_id":70329129,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70329129/facial-recogniser-does-not-support-many-requests-simultaneouly","title":"Facial recogniser does not support many requests simultaneouly"},{"tags":["python","json","request","aiogram"],"owner":{"account_id":15168120,"reputation":1,"user_id":13879024,"user_type":"registered","profile_image":"https://graph.facebook.com/2168241076532484/picture?type=large","display_name":"Сергей","link":"https://stackoverflow.com/users/13879024/%d0%a1%d0%b5%d1%80%d0%b3%d0%b5%d0%b9"},"is_answered":false,"view_count":13,"answer_count":1,"score":0,"last_activity_date":1639354857,"creation_date":1639354428,"question_id":70328750,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70328750/filter-for-duplicate-requests","title":"Filter for duplicate requests"},{"tags":["python","web","web-scraping","python-requests","http-status-code-403"],"owner":{"account_id":23600905,"reputation":1,"user_id":17637402,"user_type":"registered","profile_image":"https://graph.facebook.com/2822036108041866/picture?type=large","display_name":"Anže Škulj","link":"https://stackoverflow.com/users/17637402/an%c5%bee-%c5%a0kulj"},"is_answered":false,"view_count":19,"answer_count":0,"score":0,"last_activity_date":1639335645,"creation_date":1639066945,"last_edit_date":1639335645,"question_id":70293281,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70293281/how-can-i-bypass-403-error-in-python-using-requests","title":"How can I bypass 403 error in python using requests?"},{"tags":["python","web-scraping","tree","lxml","lxml.html"],"owner":{"account_id":10487447,"reputation":33,"user_id":7730499,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/fc9a20780b0e91ccb3771046ea4ec53f?s=256&d=identicon&r=PG&f=1","display_name":"tehais","link":"https://stackoverflow.com/users/7730499/tehais"},"is_answered":true,"view_count":142,"accepted_answer_id":54645263,"answer_count":1,"score":1,"last_activity_date":1639327537,"creation_date":1549950126,"last_edit_date":1639327537,"question_id":54643516,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/54643516/compare-string-result-from-path-requests","title":"Compare string result from path & requests"},{"tags":["python","android","apache","apache2"],"owner":{"account_id":5523589,"reputation":339,"user_id":4385799,"user_type":"registered","accept_rate":100,"profile_image":"https://www.gravatar.com/avatar/36820494e44cc535a5470f12f7b8bac7?s=256&d=identicon&r=PG&f=1","display_name":"adek111","link":"https://stackoverflow.com/users/4385799/adek111"},"is_answered":true,"view_count":252,"accepted_answer_id":49070937,"answer_count":1,"score":1,"last_activity_date":1639312085,"creation_date":1519900222,"last_edit_date":1639312085,"question_id":49047674,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/49047674/android-http-get-out-of-infinite-while-loop-with-sending-requests-to-apache-ser","title":"Android HTTP: get out of infinite while loop with sending requests to Apache server"},{"tags":["python","python-requests"],"owner":{"account_id":19341765,"reputation":425,"user_id":14141126,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/096052cee710b6ded6578b97a494f823?s=256&d=identicon&r=PG&f=1","display_name":"Robin Sage","link":"https://stackoverflow.com/users/14141126/robin-sage"},"is_answered":true,"view_count":25,"accepted_answer_id":70322109,"answer_count":1,"score":0,"last_activity_date":1639298508,"creation_date":1639296039,"last_edit_date":1639297961,"question_id":70321887,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70321887/python-requests-why-is-requestscookiejar-object-sometimes-empty","title":"Python Requests - Why is RequestsCookieJar[] object sometimes empty?"},{"tags":["python","python-3.x","beautifulsoup","python-requests"],"owner":{"account_id":12687539,"reputation":57,"user_id":9218798,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/8d36423797097405bb99465412c40983?s=256&d=identicon&r=PG&f=1","display_name":"PYJTER","link":"https://stackoverflow.com/users/9218798/pyjter"},"is_answered":false,"view_count":37,"closed_date":1639331147,"answer_count":0,"score":-4,"last_activity_date":1639293072,"creation_date":1639254295,"last_edit_date":1639293072,"question_id":70318740,"link":"https://stackoverflow.com/questions/70318740/sending-form-via-requests","closed_reason":"Not suitable for this site","title":"Sending form via requests"},{"tags":["python","visual-studio-code","pylance"],"owner":{"account_id":22243211,"reputation":111,"user_id":16477325,"user_type":"registered","profile_image":"https://lh3.googleusercontent.com/a/AATXAJwH0bQ6sVfpmvT9q1uXmYKXAybfx37fbPQgXEuJ=k-s256","display_name":"Betty Gandhi","link":"https://stackoverflow.com/users/16477325/betty-gandhi"},"is_answered":true,"view_count":7500,"answer_count":4,"score":9,"last_activity_date":1639289201,"creation_date":1629291560,"last_edit_date":1629292526,"question_id":68832892,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/68832892/why-cant-i-import-requests-in-vs-code","title":"Why can't I import requests in VS Code?"},{"tags":["python","python-2.7","python-requests","socks","urllib3"],"owner":{"account_id":1601911,"reputation":3792,"user_id":1482789,"user_type":"registered","accept_rate":50,"profile_image":"https://i.stack.imgur.com/i5WA5.jpg?s=256&g=1","display_name":"BringBackCommodore64","link":"https://stackoverflow.com/users/1482789/bringbackcommodore64"},"is_answered":true,"view_count":111850,"accepted_answer_id":39959360,"answer_count":15,"score":59,"last_activity_date":1639269007,"creation_date":1470414956,"last_edit_date":1596807172,"question_id":38794015,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/38794015/pythons-requests-missing-dependencies-for-socks-support-when-using-socks5-fro","title":"Python's requests "Missing dependencies for SOCKS support" when using SOCKS5 from Terminal"},{"tags":["python","web-scraping","beautifulsoup"],"owner":{"account_id":13908236,"reputation":206,"user_id":10042081,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/86fccb2a1c0a2db3a1e874ed5dfde330?s=256&d=identicon&r=PG&f=1","display_name":"Doesbaddel","link":"https://stackoverflow.com/users/10042081/doesbaddel"},"is_answered":true,"view_count":23,"accepted_answer_id":70318684,"answer_count":1,"score":0,"last_activity_date":1639253841,"creation_date":1639253150,"question_id":70318603,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70318603/problems-scraping-dynamic-content-with-requests-and-beautifulsoup","title":"Problems scraping dynamic content with requests and BeautifulSoup"},{"tags":["python","web-scraping","python-requests","wget","user-agent"],"owner":{"account_id":1913116,"reputation":1906,"user_id":1726366,"user_type":"registered","accept_rate":75,"profile_image":"https://www.gravatar.com/avatar/1a235490a265c8ea39f95d0aa379dda7?s=256&d=identicon&r=PG","display_name":"user1726366","link":"https://stackoverflow.com/users/1726366/user1726366"},"is_answered":true,"view_count":250784,"accepted_answer_id":27652558,"answer_count":8,"score":155,"last_activity_date":1639247527,"creation_date":1419564542,"last_edit_date":1607331256,"question_id":27652543,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/27652543/how-to-use-python-requests-to-fake-a-browser-visit-a-k-a-and-generate-user-agent","title":"How to use Python requests to fake a browser visit a.k.a and generate User Agent?"},{"tags":["python","django","web","backend","pydroid"],"owner":{"account_id":17972587,"reputation":1,"user_id":13060979,"user_type":"registered","profile_image":"https://lh3.googleusercontent.com/a-/AOh14GiwzPnMrX1nMimIxNLubmt0JDyit-_ghx_KgCPv=k-s256","display_name":"ayush kumar","link":"https://stackoverflow.com/users/13060979/ayush-kumar"},"is_answered":false,"view_count":30,"answer_count":0,"score":0,"last_activity_date":1639235821,"creation_date":1639235395,"last_edit_date":1639235821,"question_id":70316305,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70316305/connection-error-while-using-requests-module-in-my-django-project","title":"connection error while using requests module in my django project"},{"tags":["python","php","python-requests","php-curl"],"owner":{"account_id":23426087,"reputation":15,"user_id":17485552,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/81698eff6e2c4ad0e324db7cd83c31e1?s=256&d=identicon&r=PG","display_name":"devzeus","link":"https://stackoverflow.com/users/17485552/devzeus"},"is_answered":true,"view_count":20,"accepted_answer_id":70315358,"answer_count":1,"score":0,"last_activity_date":1639229272,"creation_date":1638855207,"question_id":70255370,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70255370/is-python-requests-missing-something-that-is-present-in-curl","title":"Is python requests missing something that is present in curl?"},{"tags":["python","curl","python-requests"],"owner":{"account_id":1429013,"reputation":2875,"user_id":1353861,"user_type":"registered","accept_rate":100,"profile_image":"https://www.gravatar.com/avatar/1579042ef77b9670ed2e189186d2e268?s=256&d=identicon&r=PG","display_name":"Shagun Sodhani","link":"https://stackoverflow.com/users/1353861/shagun-sodhani"},"is_answered":true,"view_count":19584,"accepted_answer_id":24970508,"answer_count":4,"score":21,"last_activity_date":1639226340,"creation_date":1406372610,"last_edit_date":1464302458,"question_id":24970333,"content_license":"CC BY-SA 3.0","link":"https://stackoverflow.com/questions/24970333/curl-works-but-not-python-requests","title":"Curl works but not Python requests"},{"tags":["python","python-3.x","python-requests"],"owner":{"account_id":23548891,"reputation":3,"user_id":17591917,"user_type":"registered","profile_image":"https://lh3.googleusercontent.com/a-/AOh14Gjp92M-rpFqnWLjc8A2nVU84m78iaQo8LxgI5M9=k-s256","display_name":"Jeffrey wang","link":"https://stackoverflow.com/users/17591917/jeffrey-wang"},"is_answered":false,"view_count":18,"answer_count":1,"score":0,"last_activity_date":1639176486,"creation_date":1639086136,"question_id":70297075,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70297075/error-when-getting-value-from-a-php-file-with-requests","title":"Error when getting value from a php file with requests"},{"tags":["python","python-3.x","python-requests"],"owner":{"account_id":426537,"reputation":11045,"user_id":807797,"user_type":"registered","accept_rate":72,"profile_image":"https://www.gravatar.com/avatar/4072657366a6ad674347c2a216318623?s=256&d=identicon&r=PG","display_name":"CodeMed","link":"https://stackoverflow.com/users/807797/codemed"},"is_answered":false,"view_count":20,"answer_count":0,"score":0,"last_activity_date":1639174682,"creation_date":1639174682,"question_id":70310975,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70310975/python-requests-json-response-fails-to-print-to-console","title":"python requests json response fails to print to console"},{"tags":["python","python-3.x","python-asyncio","aiohttp","pytest-aiohttp"],"owner":{"account_id":15437846,"reputation":23,"user_id":11137424,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/7dd686925c1ad482542497caf5904a66?s=256&d=identicon&r=PG&f=1","display_name":"Last_crusaider","link":"https://stackoverflow.com/users/11137424/last-crusaider"},"is_answered":true,"view_count":4127,"accepted_answer_id":55250776,"answer_count":1,"score":2,"last_activity_date":1639166135,"creation_date":1553031726,"last_edit_date":1639166135,"question_id":55250420,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/55250420/aiohttp-async-session-requests","title":"Aiohttp async session requests"},{"tags":["python","python-3.x","python-requests"],"owner":{"account_id":22132220,"reputation":341,"user_id":16383578,"user_type":"registered","profile_image":"https://www.gravatar.com/avatar/a6b1c642dc9b2709eff08d541d42aba3?s=256&d=identicon&r=PG&f=1","display_name":"Thyebri","link":"https://stackoverflow.com/users/16383578/thyebri"},"is_answered":true,"view_count":335,"answer_count":2,"score":8,"last_activity_date":1639160015,"creation_date":1628942863,"question_id":68783157,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/68783157/python-3-requests-how-to-force-use-a-new-connection-for-each-request","title":"Python 3 requests how to force use a new connection for each request?"},{"tags":["python","asynchronous","python-requests","python-asyncio"],"owner":{"account_id":21744301,"reputation":11,"user_id":16051219,"user_type":"registered","profile_image":"https://lh3.googleusercontent.com/a/AATXAJxA5U0WVtb-F7sU25wo4ToWFoienn4yfayhC0uJ=k-s256","display_name":"James Deen","link":"https://stackoverflow.com/users/16051219/james-deen"},"is_answered":false,"view_count":22,"answer_count":0,"score":0,"last_activity_date":1639155089,"creation_date":1639155089,"question_id":70307892,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70307892/how-to-make-many-async-http-requests-using-prepared-requests-in-python","title":"How to make many async HTTP requests using prepared-requests in Python"},{"tags":["python","python-requests"],"owner":{"account_id":8393738,"reputation":225,"user_id":6301635,"user_type":"registered","accept_rate":33,"profile_image":"https://www.gravatar.com/avatar/5ef8efde9adf65532d2ca3652dbf50c8?s=256&d=identicon&r=PG&f=1","display_name":"Hobbit36","link":"https://stackoverflow.com/users/6301635/hobbit36"},"is_answered":true,"view_count":24553,"accepted_answer_id":45267074,"answer_count":3,"score":17,"last_activity_date":1639154266,"creation_date":1500824937,"last_edit_date":1639154266,"question_id":45267003,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/45267003/python-requests-hanging-freezing","title":"Python Requests hanging/freezing"},{"tags":["python","python-requests","grequests"],"owner":{"account_id":7043862,"reputation":197,"user_id":5395342,"user_type":"registered","accept_rate":50,"profile_image":"https://i.stack.imgur.com/PuPMG.png?s=256&g=1","display_name":"Omrii","link":"https://stackoverflow.com/users/5395342/omrii"},"is_answered":true,"view_count":455,"accepted_answer_id":67404033,"answer_count":1,"score":1,"last_activity_date":1639146835,"creation_date":1597433691,"last_edit_date":1639146835,"question_id":63419061,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/63419061/python-webscraping-grequests-vs-mult-threaded-requests","title":"Python Webscraping: grequests vs. mult-threaded requests?"},{"tags":["python","api","python-requests","spotify"],"owner":{"account_id":23610175,"reputation":1,"user_id":17645312,"user_type":"registered","profile_image":"https://lh3.googleusercontent.com/a/AATXAJyOyXXzjbyVoNDKIYka6B8KNlMJnRW53tmhWPIE=k-s256","display_name":"Stan Waldron","link":"https://stackoverflow.com/users/17645312/stan-waldron"},"is_answered":false,"view_count":14,"answer_count":0,"score":0,"last_activity_date":1639146581,"creation_date":1639146581,"question_id":70306010,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70306010/spotify-web-api-python-requests-unable-to-access-public-playlist-information","title":"Spotify Web API python requests unable to access public playlist information"},{"tags":["python","web-scraping","beautifulsoup","http-status-code-429"],"owner":{"account_id":17038651,"reputation":1,"user_id":12327129,"user_type":"registered","profile_image":"https://lh3.googleusercontent.com/a-/AAuE7mAc4L8XjZX48v2UTBVSQMKaBeIfm27A2Z4zPgMz1Q=k-s256","display_name":"Salman Khalid","link":"https://stackoverflow.com/users/12327129/salman-khalid"},"is_answered":false,"view_count":49,"answer_count":0,"score":-1,"last_activity_date":1639141984,"creation_date":1639139501,"question_id":70304557,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70304557/http-status-code-429-too-many-requests-python","title":"http-status-code 429: Too many requests, Python"},{"tags":["python","python-requests","request"],"owner":{"account_id":22882079,"reputation":72,"user_id":17023536,"user_type":"registered","profile_image":"https://lh3.googleusercontent.com/a/AATXAJwkzXBwldRrMMIz4OLj_mAvNW-I0Rr94SkzTAHb=k-s256","display_name":"jay kishan","link":"https://stackoverflow.com/users/17023536/jay-kishan"},"is_answered":false,"view_count":37,"answer_count":1,"score":-1,"last_activity_date":1639138989,"creation_date":1638963877,"last_edit_date":1639138989,"question_id":70274446,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70274446/requests-not-loading-the-content-as-web-browser-gives-python","title":"Requests not loading the content as web Browser gives Python"},{"tags":["python","selenium","selenium-webdriver","aws-lambda","phantomjs"],"owner":{"account_id":4752023,"reputation":2013,"user_id":3841825,"user_type":"registered","accept_rate":84,"profile_image":"https://www.gravatar.com/avatar/7bbc51121f89da676bf228cc47282952?s=256&d=identicon&r=PG&f=1","display_name":"jstnchng","link":"https://stackoverflow.com/users/3841825/jstnchng"},"is_answered":false,"view_count":12,"answer_count":0,"score":0,"last_activity_date":1639111626,"creation_date":1639110019,"last_edit_date":1639111626,"question_id":70299720,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70299720/http-client-remotedisconnected-error-in-selenium-for-successive-requests","title":"http.client.RemoteDisconnected error in selenium for successive requests"},{"tags":["python","python-requests","attributes"],"owner":{"account_id":20655633,"reputation":79,"user_id":15164825,"user_type":"registered","profile_image":"https://graph.facebook.com/1404827529870895/picture?type=large","display_name":"FrGe","link":"https://stackoverflow.com/users/15164825/frge"},"is_answered":false,"view_count":23,"answer_count":0,"score":1,"last_activity_date":1639103542,"creation_date":1639059559,"last_edit_date":1639103542,"question_id":70291508,"content_license":"CC BY-SA 4.0","link":"https://stackoverflow.com/questions/70291508/python-attributeerror-module-requests-has-no-attribute-requesturl","title":"Python AttributeError: module 'requests' has no attribute 'requestURL'"}],"has_more":true,"quota_max":300,"quota_remaining":291}'
In [ ]:
res = requests.post ("https://google.com", data = {"key" : "value"})
res.text
Out[ ]:
'<!DOCTYPE html>\n<html lang=en>\n  <meta charset=utf-8>\n  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">\n  <title>Error 405 (Method Not Allowed)!!1</title>\n  <style>\n    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n  </style>\n  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\n  <p><b>405.</b> <ins>That’s an error.</ins>\n  <p>The request method <code>POST</code> is inappropriate for the URL <code>/</code>.  <ins>That’s all we know.</ins>\n'

Working with Flask. Minimal example

Flask is another third party module, so you have to install it first.

In [2]:
!pip install flask
Requirement already satisfied: flask in /usr/local/lib/python3.6/dist-packages (1.1.2)
Requirement already satisfied: click>=5.1 in /usr/local/lib/python3.6/dist-packages (from flask) (7.1.2)
Requirement already satisfied: itsdangerous>=0.24 in /usr/local/lib/python3.6/dist-packages (from flask) (1.1.0)
Requirement already satisfied: Jinja2>=2.10.1 in /usr/local/lib/python3.6/dist-packages (from flask) (2.11.2)
Requirement already satisfied: Werkzeug>=0.15 in /usr/local/lib/python3.6/dist-packages (from flask) (1.0.1)
Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.6/dist-packages (from Jinja2>=2.10.1->flask) (1.1.1)

The simplest examplt of a web application with Flask:

In [5]:
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, world!'

# app.run()

The syntax above uses a decorator, a function app.route uses the function hello_world inside it.

Decorators are a slightly complicated topic, so for the purpose of working with Flask, you can assume it works the following way:

  1. The code above defines a page, a response for a particular request. Similar to how APIs have their endpoints - addresses you should use to get particular types of data.
  2. @app.route - your application is in the variable app, as defined above. Like df/data for pandas DataFrame. Flask applications have a method route, like data frames have df.mean() or lists have .append().
  3. ('/') - the input parameter of app.route() is the path to your page in the URL. For example, my-flask-web-app.ru/. It's the / in this link/
  4. The Python function itself does whatever you want it to do. Reads data from files, plots graph, computes data.
  5. The return value of the function is the html page you will display to the user. In this case, the user will see Hello, world! as just text because this is all the html that is returned.

We can manage HTTP requests by using methods argument of decorator.

We can also put html tags in the output.

In [ ]:
@app.route('/', methods=['GET'])
def hello_world2():
    return '<h1>Hello, world!</h1>'

Other requests will not be available after we select only 'GET' in the list

Let's create an HTML file so we don't write the whole page inline as a string.

<!DOCTYPE html>
<html>
    <head>
        <title>Web server minimal example</title>
        <style>
        h1 {
          color: #880000;
        }</style>

    </head>
  <body>
    <div>
        <h1>Hello from the html page</h1>
    </div>
  </body>
</html>

Now if we put the file with code and the html page in the same folder, we can use the file in the output of the hello_world function.

In [ ]:
@app.route('/', methods=['GET'])
def hello_world3():
    with open('index.html') as f:
        content = f.read()
    return content

More complex example

Now let's make a web application that does something more than printing greetings.

We need the following parts:

  1. An html page where the results will be shown
    1. Some styling for the html page
  2. Functions that do some work. In our case, plotting graphs.
  3. A way to create the html page using the result of the functions. This will be done using a Jinja template.
  4. Connecting different functions to corresponding paths on the site/app. This will be done using @app.route('/path') decorators
  5. Connecting pages together so the user can navigate. This will be done using links in the html page.

Lets create the page and its style.

style.css:

.vertical-menu {
  width: 200px; /* Set a width if you like */
}

.vertical-menu a {
  background-color: #eee; /* Grey background color */
  color: black; /* Black text color */
  display: block; /* Make the links appear below each other */
  padding: 12px; /* Add some padding */
  text-decoration: none; /* Remove underline from links */
}

.vertical-menu a:hover {
  background-color: #ccc; /* Dark grey background on mouse-over */
}

.vertical-menu a.active {
  background-color: #015cab; /* Add a green color to the "active/current" link */
  color: white;
}

index.html

<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<html>
    <head>
        <title>My Web Server</title>
        <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}?202012100341">
    </head>
  <body>
    <div>

        <div class="vertical-menu">
          <a href="#" class="active">Home</a>
            {% for text, link in links.items() %}
                <a href="{{ link }}">{{ text }}</a>
            {% endfor %}
        </div>
    </div>
  </body>
</html>

Here we used JINJA. Jinja is a web template engine for the Python programming language. It can simplify creating html template for your service.

The text in curly braces {} is the part of the template that will be generated. Everything else is HTML.

The function render_template takes a Jinja template and fills in the variables with actual values. It returns the final version of the html file, and we can use this result as the response to the user.

In our case, the only part of the page that will change is the image. So we can use another function to set all parameters except the image.

In [ ]:
def render_index (image = None):
    return render_template("index.html", links=links, image = (image, image), code=time.time())

The links argument here is a dictionary connecting link text (what use user sees) and link path (what your application uses).

In [ ]:
links = {"Download" : "/download",
         "Pairplot" : "/pairplot",
         "Fair vs Pclass"  : "fair_vs_pclass",
         "PClass vs Sex" : "pclass_vs_sex"}

Lets make first url for our web server - download. by clicking this option we will download our titanic data as is

In [ ]:
@app.route('/download', methods=['GET'])
def download_data():
    return send_file("data/titanic_train.csv", as_attachment=True)

Lets make a plot showing distributions of the data.

In [ ]:
@app.route('/pairplot', methods=['GET'])
def pairplot():
    import seaborn as sns
    import pandas as pd
    data = pd.read_csv ("data/titanic_train.csv")
    sns_plot = sns.pairplot(data, hue="Survived")
    sns_plot.savefig("static/tmp/pairplot.png")
    return render_template("index.html", links=links, image = ("pairplot.png", "pairplot"))

Html + jinja

{% if image != None %}
    <div style="margin-left:20%;margin-top:3%;border: 2px;">
        <img src="{{ url_for('static', filename=image[0]) }}" alt="{{ image[1] }}" style="max-width:1000px;border: 5px solid #555;">
    </div>
{% endif %}

Let's make other charts we implemented last time

In [ ]:
@app.route('/fair_vs_pclass', methods=['GET'])
def fair_vs_pclass():
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    data = pd.read_csv ("data/titanic_train.csv")
    filtered_data = data.query('Fare < 200')
    sns.boxplot(x='Pclass', y='Fare', data=filtered_data, ax=ax)
    plt.savefig('static/tmp/fair_vs_pclass.png')

    return render_index ("fair_vs_pclass.png")
In [ ]:
@app.route('/pclass_vs_sex', methods=['GET'])
def pclass_vs_sex():
    import matplotlib.pyplot as plt

    fig, ax = plt.subplots()
    data = pd.read_csv ("data/titanic_train.csv")
    result = {}
    for (cl, sex), sub_df in data.groupby(['Pclass', 'Sex']):
        result[f"{cl} {sex}"] = sub_df['Age'].mean()

    plt.bar (result.keys(), result.values())
    plt.savefig('static/tmp/pclass_vs_sex.png')
    return render_index ("pclass_vs_sex.png")

The final version of the HTML file:

<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<html>
    <head>
        <title>My Web Server</title>
        <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}?202012100341">
    </head>
<body>

<div class="vertical-menu" style="float:left;width:15%;">
  <a href="/" class="active">Home</a>
    {% for text, link in links.items() %}
        <a href="{{ link }}">{{ text }}</a>
    {% endfor %}
</div>

{% if image != None %}
    <div style="margin-left:20%;margin-top:3%;border: 2px;">
        <img src="{{ url_for('static', filename='tmp/' + image[0]) }}?{{code}}" alt="{{ image[1] }}" style="max-width:1000px;border: 5px solid #555;">
    </div>
{% endif %}


</body>
</html>

The structure of files in your project folder should be like this.

app.py
data/
     titanic_train.csv
static/
     style.css
     tmp/
templates/
     index.html

Local Deployment

For developing and testing purposes it is usually helpful to be able to run the application locally to make sure it works correctly.

In [ ]:
from flask import Flask
from flask import send_file
from flask import render_template
import seaborn as sns
import pandas as pd
import time


# run the Flask web server from Python
app.run()

You can double check the structure of your project by going to this link and comparing it with the folder structure there.

https://github.com/PGeorge1/example20201213