Дархости аввал
Чаро дархостҳои HTTP лозиманд
Барнома метавонад аз компютери дигар маълумот гирад: ҷадвал, рӯйхати молҳо, обу ҳаво ё натиҷаҳои ҷустуҷӯ. Барои ин сервер API — маҷмӯи суроғаҳо ва қоидаҳои муоширатро пешниҳод мекунад. Китобхонаи requests фиристодани дархости HTTP ва хондани ҷавобро иҷро мекунад, шумо бошед бо сатрҳо, луғатҳо ва рӯйхатҳои маъмулии Python кор мекунед.
HTTP ба мубодилаи мактубҳо монанд аст: муштарӣ суроға ва амалро нишон медиҳад, сервер рамзи натиҷа, сарлавҳаҳо ва баданро мефиристад. GET амали «гирифтан» аст. URL суроғаи пурраи манбаъ мебошад. Ҷавоб аз маълумоти хизматӣ ва муҳтаво иборат аст; рамзи 200 ва матни саҳифа қисмҳои гуногуни як ҷавобанд.
Сервери омӯзишӣ: натиҷаи такроршаванда
API-ҳои воқеӣ тағйир меёбанд, бинобар ин мисолҳои ин лексия сервери хурдеро дар компютери шумо истифода мебаранд. Блокҳоро бо тартиб дар як раванди Python иҷро кунед. Блоки аввал танҳо муҳити санҷиш аст: ҳоло сохтори http.server-ро аз ёд кардан шарт нест. Он JSON-и собит медиҳад, вале барои /missing рамзи 404 бармегардонад. Система порти озодро интихоб мекунад.
import json
import os
import threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import requests
os.environ["NO_PROXY"] = "127.0.0.1,localhost"
class Handler(BaseHTTPRequestHandler):
def log_message(self, *args):
pass
def do_GET(self):
data = json.dumps({"name": "Mira", "active": True,
"tags": ["python", "http"]}).encode("utf-8")
self.send_response(404 if self.path == "/missing" else 200)
self.send_header("Content-Type", "application/json; charset=utf-8")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
base = f"http://127.0.0.1:{server.server_port}"
print(base.split(":")[1].strip("/"))
Барориш:
127.0.0.1
127.0.0.1 ҳамин компютер аст. Ҷараён (thread) имкон медиҳад, ки сервер ҳангоми фиристодани дархостҳо аз коди асосӣ ҷавоб диҳад. NO_PROXY суроғаи маҳаллиро аз истифодаи proxy хориҷ мекунад. Санҷиши масъалаҳои курс муҳити монанд месозад, бинобар ин натиҷа аз интернет ё қурби имрӯза вобаста нест.
Гирифтани Response
requests.get объекти ҷавоб — Response-ро бармегардонад. timeout=5 интизории пайвастшавӣ ва таваққуфи хонданро маҳдуд мекунад. Ин соатсанҷи тамоми боргирӣ нест: агар маълумот пайваста ояд, дархост метавонад беш аз панҷ сония давом кунад. Бе timeout китобхона чунин маҳдудият намегузорад.
r = requests.get(base + "/profile", timeout=5)
print(type(r).__name__, r.status_code, r.ok)
print(r.headers["content-type"])
Барориш:
Response 200 True
application/json; charset=utf-8
status_code адад аст, ok аломати мантиқии рамзи аз 400 хурд мебошад. Сарлавҳаҳо баданро тавсиф мекунанд: Content-Type формат ва рамзгузориро мегӯяд. Номи сарлавҳа ба калон ё хурд будани ҳарфҳо вобаста нест, бинобар ин content-type кор мекунад. Барои сарлавҳаи ихтиёрӣ r.headers.get("name") аз индексгузорӣ бехатартар аст: ҳангоми набудани калид индексгузорӣ KeyError медиҳад.
Байтҳо, матн ва JSON — се намоиш
Шабака байтҳо мефиристад. r.content онҳоро бе табдил ба матн медиҳад. r.text байтҳоро бо назардошти рамзгузории ҷавоб ба матн табдил медиҳад. JSON формати матнии мубодилаи маълумот аст; r.json() онро таҳлил карда, объектҳои Python месозад. Ин метод дархости нав намефиристад ва «нусхаи дигари» ҷавобро намегирад.
print(type(r.content).__name__)
print(r.text)
data = r.json()
print(type(data).__name__, data["name"], data["active"])
print(data["tags"][1])
Барориш:
bytes
{"name": "Mira", "active": true, "tags": ["python", "http"]}
dict Mira True
http
Объекти JSON ба dict, массив ба list, true ва false ба True ва False, null ба None табдил меёбанд. Аввал сохторро фаҳмед: дар ин ҷо tags рӯйхат ва name сатр аст. HTML, сатри холӣ ё JSON-и вайрон ҳангоми json() хатои таҳлил медиҳанд. Ҳатто сарлавҳаи application/json дурустии муҳтаворо кафолат намедиҳад.
Рамзи ҳолат ва истисно фарқ доранд
Рамзҳои 2xx коркарди муваффақро нишон медиҳанд: 200 ҷавоби одӣ, 201 сохтан, 204 муваффақият бе бадан аст. 3xx ба равонасозӣ дахл дорад; GET одатан худкор аз он мегузарад. 4xx мушкили дархост ё дастрасиро ифода мекунад, масалан 401 ва 404. 5xx аз нокомии сервер хабар медиҳад.
Ҷавоби 404 худ аз худ барномаро қатъ намекунад. Сервер бо HTTP ҷавоб дод, ҳарчанд манбаъ ёфт нашуд. raise_for_status() рамзи 4xx ё 5xx-ро ба HTTPError табдил медиҳад, агар коркард бо истисноҳо барои барнома муносиб бошад.
missing = requests.get(base + "/missing", timeout=5)
print(missing.status_code, missing.ok)
try:
missing.raise_for_status()
except requests.HTTPError:
print(type(missing).__name__, missing.status_code)
Барориш:
404 False
Response 404
Диққат диҳед: ok маънои «ҳатман 200»-ро надорад ва маънои JSON-ро намесанҷад. Ҳангоми нокомии шабака вазъ дигар аст: ҷавоби пурра шояд умуман набошад. Ин хатоҳоро дар мавзӯи timeout ва такрорҳо меомӯзем.
Аз ҷавоб то маълумоти муфид
Пас аз гирифтани JSON коркарди одии Python оғоз мешавад. Масалан, номҳои кортҳои фаъолро интихоб кардан мумкин аст. Дар ин ҷо маълумот мустақим дар код навишта шудааст, то кори рӯйхатро аз шабака ҷудо омӯзем.
cards = [{"name": "A", "enabled": True},
{"name": "B", "enabled": False},
{"name": "C", "enabled": True}]
names = [card["name"] for card in cards if card["enabled"]]
print(names)
print(len(names))
Барориш:
['A', 'C']
2
Рӯйхати холӣ низ маълумоти дуруст аст. Пеш аз гирифтани унсур бо индекс ё ёфтани максимум ин ҳолатро ба назар гиред. Агар тартиб муҳим бошад, тартиби аслиро нигоҳ доред ва шарти баробарии қиматҳоро бодиққат хонед. Унсури аввали ҷавоб худкор беҳтарин нест.
Воҳидҳои ченак дар API
Ададро бе воҳиди ченак осон нодуруст мефаҳманд. Нархи қуттӣ ба нархи як дона баробар нест. Дар мисоли хурд нарх барои баста бо воҳиди пулии шартӣ дода шудааст.
pack = {"units": 20, "price": 150}
unit_price = pack["price"] / pack["units"]
print(f"{unit_price:.2f}")
Барориш:
7.50
Дар қурби Бонки марказӣ фикри монанд ҳаст: Value ба миқдори Nominal тааллуқ дорад, на ҳатман ба як воҳиди асъор. Ҳангоми хондани ҳар API муайян кунед, ки адад чиро ифода мекунад. Рамзи асъор ва номи майдон қисми протоколанд; онҳоро худсарона иваз накунед. Масъалаҳо қурбҳои собити омӯзиширо истифода мебаранд; тугмаи «Дар компютери худ иҷро кардан» мисолҳои сомонаҳои воқеиро аз блоки if __name__ == "__main__" иҷро мекунад.
Дар дохил чӣ рӯй медиҳад
requests суроға ва сарлавҳаҳоро омода мекунад, пайваст мешавад, GET мефиристад ва ҷавобро мехонад. Дар дархости одӣ бадан то бозгашти get боргирӣ мешавад. Сипас text муҳтаворо ба матн табдил медиҳад, json() бошад сохторро таҳлил мекунад. Ин марҳилаҳо ҷудоанд: расидани ҷавоб дурустии формат ва мавҷудияти майдонҳои лозимиро кафолат намедиҳад.
Кори сервери омӯзиширо анҷом медиҳем. Қимати -1 маънои баста шудани socket-и онро дорад.
server.shutdown()
server.server_close()
print(server.fileno())
Барориш:
-1
Хатоҳои маъмул ва ислоҳи онҳо
requests.get(base)бе маҳдудият. Агар сервер хомӯш бошад, барнома метавонад беохир интизор шавад.requests.get(base, timeout=5)нависед ва истисноҳои шабакаро коркард кунед.- Танҳо
r.status_code == 200-ро муваффақ донистан. Ҷавобҳои 201 ва 204 нодуруст рад мешаванд. Қоидаи API-ро санҷед; барои ошкор кардани хатои HTTP азraise_for_status()ёokистифода баред. r.jsonбе қавс. Ба ҷойи маълумот объекти метод мегиред.r.json()-ро фаро хонед, сипас сохтори интизориро санҷед.r.json()баъди 204. Ҷавоби муваффақ метавонад холӣ бошад ва таҳлил хато диҳад. Пеш аз таҳлил рамз ва мавҷудияти баданро ба назар гиред.r.text.encode("utf-8")барои тасвир. Табдил ба матн ва бозгашт метавонад байтҳоро тағйир диҳад. Барои файлr.contentгиред; хондани ҷараёнии файлҳои калонро баъд меомӯзем.
Ёддошт
| Амал | Восита |
|---|---|
| Гирифтани манбаъ | requests.get(url, timeout=5) |
| Донистани ҳолат | r.status_code, r.ok |
| Ба истисно табдил додани хатои HTTP | r.raise_for_status() |
| Хондани матн / байтҳо | r.text / r.content |
| Таҳлили JSON | r.json() |
| Хондани сарлавҳаи ихтиёрӣ | r.headers.get("Content-Type") |
Аввал расидан ва ҳолат, сипас формат ва сохторро санҷед; баъд бо назардошти воҳидҳои ченак ҳисоб кунед.