3.1. Web Stdlibï
3.1.1. http.HTTPStatusï
Using statuses:
from http import HTTPStatus
HTTPStatus.OK
HTTPStatus.OK == 200
HTTPStatus.OK.value
HTTPStatus.OK.phrase
HTTPStatus.OK.description
list(HTTPStatus)
Most common statuses:
from http import HTTPStatus
HTTPStatus.OK # 200
HTTPStatus.CREATED # 201
HTTPStatus.MOVED_PERMANENTLY # 301
HTTPStatus.FOUND # 302
HTTPStatus.BAD_REQUEST # 400
HTTPStatus.UNAUTHORIZED # 401
HTTPStatus.FORBIDDEN # 403
HTTPStatus.METHOD_NOT_ALLOWED # 405
HTTPStatus.NOT_FOUND # 404
HTTPStatus.INTERNAL_SERVER_ERROR # 500
All statuses:
Code |
Description |
|---|---|
100 |
|
101 |
|
102 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
226 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
307 |
|
308 |
|
400 |
|
401 |
|
402 |
|
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 |
|
415 |
|
416 |
|
417 |
|
421 |
|
422 |
|
423 |
|
424 |
|
426 |
|
428 |
|
429 |
|
431 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 |
|
505 |
|
506 |
|
507 |
|
508 |
|
510 |
|
511 |
|
3.1.2. urllibï
ÅciÄ
ganie danych z internetu, które trzeba rozpakowaÄ, Dane sÄ
w formacie TSV (tab separator values), można je rozpakowaÄ moduÅem CSV i podaÄ jako delimiter='\t'
import os
import urllib.request
import zipfile
data_path = 'data'
os.makedirs(data_path, exist_ok=True)
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00228/smsspamcollection.zip'
file_name = url.split('/')[-1]
dest_file = os.path.join(data_path, file_name)
data_file = 'SMSSpamCollection'
data_full = os.path.join(data_path, data_file)
urllib.request.urlretrieve(url, dest_file)
with zipfile.ZipFile(dest_file) as zip_file:
zip_file.extract(data_file, path=data_path)
3.1.3. http.serverï
http.serveris not recommended for production. It only implements basic security checks.https://docs.python.org/3.7/library/http.server.html#module-http.server
Simple HTTP Server:
$ python -m http.server 8000 --bind 127.0.0.1
Own HTTP Sever:
import re
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler
from http.server import HTTPServer
SERVER = ('localhost', 8080)
class RequestHandler(BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(HTTPStatus.OK)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
self.send_response(HTTPStatus.OK)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write('<html>')
self.wfile.write('<body>Hello World!</body>')
self.wfile.write('</html>')
def do_POST(self):
if re.search('/api/v1/*', self.path):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
self.send_response(HTTPStatus.OK)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write('<html>')
self.wfile.write('<body>Hello World!</body>')
self.wfile.write('</html>')
try:
print('Starting server {SERVER}, use <Ctrl-C> to stop')
httpd = HTTPServer(SERVER, RequestHandler)
httpd.serve_forever()
except KeyboardInterrupt:
print('^C received, shutting down the web server...')
httpd.socket.close()
Threaded server with JSON response:
http.server.ThreadingHTTPServersince Python 3.7import json from http import HTTPStatus from http.server import ThreadingHTTPServer from http.server import BaseHTTPRequestHandler class RequestHandler(BaseHTTPRequestHandler): def do_GET(self): data = {'username': 'alice', 'password': 'secret'} response = bytes(json.dumps(data), 'UTF-8') self.send_response(HTTPStatus.OK) self.send_header('Content-Type', 'application/json; charset=utf-8') self.end_headers() self.wfile.write(response) self.server.path = self.path def run(host='127.0.0.1', port=8080): print(f'Starting server on {host}:{port}, use <Ctrl-C> to stop') httpd = ThreadingHTTPServer((host, port), RequestHandler) httpd.serve_forever() if __name__ == '__main__': run()
3.1.4. http.clientï
3.1.5. Connectingï
h1 = http.client.HTTPConnection('www.python.org')
h2 = http.client.HTTPConnection('www.python.org:80')
h3 = http.client.HTTPConnection('www.python.org', 80)
h4 = http.client.HTTPConnection('www.python.org', 80, timeout=10)
3.1.6. GET Requestï
import http.client
conn = http.client.HTTPSConnection("www.python.org")
conn.request("GET", "/")
response = conn.getresponse()
response.status # 200
response.reason # OK
data = response.read() # This will return entire content.
conn.close()
3.1.7. GET Request in chunksï
import http.client
conn = http.client.HTTPSConnection("www.python.org")
conn.request("GET", "/")
response = conn.getresponse()
# The following example demonstrates reading data in chunks.
while not response.closed:
print(response.read(200)) # 200 bytes
3.1.8. GET Request to Not Existing Resourceï
import http.client
conn = http.client.HTTPSConnection("www.python.org")
conn.request("GET", "/parrot.spam")
response = conn.getresponse()
response.status # 404
response.reason # Not Found
data = response.read()
print(data)
# b'<!doctype html> ... </body>\n</html>\n'
conn.close()
3.1.9. HEAD Requestï
import http.client
conn = http.client.HTTPSConnection("www.python.org")
conn.request("HEAD", "/")
response = conn.getresponse()
response.status # 200
response.reason # OK
print(response.headers)
# Server: nginx
# Content-Type: text/html; charset=utf-8
# X-Frame-Options: SAMEORIGIN
# x-xss-protection: 1; mode=block
# X-Clacks-Overhead: GNU Terry Pratchett
# Via: 1.1 varnish
# Content-Length: 48925
# Accept-Ranges: bytes
# Date: Tue, 06 Nov 2018 11:06:52 GMT
# Via: 1.1 varnish
# Age: 599
# Connection: keep-alive
# X-Served-By: cache-iad2142-IAD, cache-fra19148-FRA
# X-Cache: HIT, HIT
# X-Cache-Hits: 1, 2
# X-Timer: S1541502413.680933,VS0,VE0
# Vary: Cookie
# Strict-Transport-Security: max-age=63072000; includeSubDomains
conn.close()
3.1.10. POST Requestï
import http.client
import urllib.parse
params = urllib.parse.urlencode({
'@number': 12524,
'@type': 'issue',
'@action': 'show'
})
headers = {
"Content-type": "application/x-www-form-urlencoded",
"Accept": "text/plain"
}
conn = http.client.HTTPSConnection("bugs.python.org")
conn.request("POST", "/", params, headers)
response = conn.getresponse()
response.status # 302
response.reason # 'Found'
data = response.read()
print(data)
# b'Redirecting to <a href="https://bugs.python.org/issue12524">https://bugs.python.org/issue12524</a>'
conn.close()
3.1.11. Basic Authï
import http.client
import json
from http import HTTPStatus
from base64 import b64encode
USERNAME = 'my_username'
TOKEN = 'my_token'
auth = bytes(f'{USERNAME}:{TOKEN}', 'utf-8')
auth = b64encode(auth).decode('ascii')
headers = {
'Authorization': f'Basic {auth}',
'User-Agent': 'Python http.client',
'Accept': 'application/json'
}
conn = http.client.HTTPSConnection(host="api.github.com", port=443)
conn.request("GET", "/users", headers=headers)
response = conn.getresponse()
if response.status == HTTPStatus.OK:
body = response.read().decode()
data = json.loads(body)
print(data)
conn.close()
3.1.12. Assignmentsï
3.1.12.1. REST APIï
- About:
Name: REST API
Difficulty: medium
Lines: 60
Minutes: 21
- License:
Copyright 2025, Matt Harasymczuk <matt@python3.info>
This code can be used only for learning by humans (self-education)
This code cannot be used for teaching others (trainings, bootcamps, etc.)
This code cannot be used for teaching LLMs and AI algorithms
This code cannot be used in commercial or proprietary products
This code cannot be distributed in any form
This code cannot be changed in any form outside of training course
This code cannot have its license changed
If you use this code in your product, you must open-source it under GPLv2
Exception can be granted only by the author (Matt Harasymczuk)
- English:
Create free account on Github and confirm email
Go to website https://github.com/settings/tokens
- Polish:
ZaÅóż darmowe konto na Github i potwierdź email
Wejdź na stronÄ internetowÄ https://github.com/settings/tokens
Wygeneruj w swoim profilu token (scope
public_repo- Access public repositories)UżywajÄ c biblioteki standardowej w Pythonie
ZaciÄ gnij informacje o repozytoriach użytkownika Django na https://github.com
Każdy request uwierzytelnij za pomocÄ Basic Auth i swojego Access Tokena
NastÄpnie przeglÄ dnij listÄ z poziomu Pythona i znajdź URL dla repozytorium
djangoPrzeglÄ dnij to repozytorium i jego listÄ komitów
Podaj datÄ i opis ostatniego komita
Znajdź numery ID zadaŠ(
Fixed #...) z issue trackera, które zostaÅy rozwiÄ zane w ostatnim miesiÄ cuUruchom doctesty - wszystkie muszÄ siÄ powieÅÄ
- Hints:
$ curl -X GET https://api.github.com/orgs/django/repos $ curl -X GET https://api.github.com/repos/django/django/commits
... "name": "django", "fullname": "django/django", ... # wyszukaj "commits_url"