requests en httpx, nu je het weet · oefening
httpx, dezelfde ideeën
httpx is een tweede httpx.Client is zijn sessie: hij bewaart with. Ook zijn aanroepen zien er vertrouwd uit, client.get(url), client.post(url, auth=...), client.request("GET", url), en de httpx.get en httpx.post, net zoals requests requests.get heeft. Dus de regel die je in les 2 schreef, leest hier hetzelfde:
client = httpx if client is None else client
response = client.get(url, timeout=timeout)
De verschillen zitten in de standaardinstellingen, en elk ervan is een beslissing die je in deze cursus al met de hand hebt genomen:
| requests | httpx | |
|---|---|---|
gevolgd, tenzij allow_redirects=False | niet gevolgd, tenzij follow_redirects=True | |
| time-out | geen, tenzij je er een meegeeft | 5 seconden voor elke fase |
raise_for_status() | werpt op bij 4xx en 5xx | werpt op bij elke status buiten 2xx, 3xx inbegrepen |
auth= met tekst | gecodeerd als Latin-1 | gecodeerd als |
| zijn | subklassen van OSError | geen subklassen van OSError |
Hier is waar je elke beslissing nam. Je follow volgde alleen omdat je hem aanriep; kale http.client deed dat nooit. Je time-outs waren altijd je eigen getallen, ingesteld op elke verbinding. classify zette een 3xx in een eigen klasse, redirection, los van client- en serverfouten. basic_header codeerde UTF-8. En je code uit hoofdstuk 3 ving TimeoutError af, die een OSError is, net als de exceptions van requests. httpx besliste bij elk ervan gewoon anders, dus code die van de ene bibliotheek naar de andere verhuist, moet je rij voor rij lezen, en niet blind vertrouwen dat hij zich hetzelfde gedraagt.
Alleen volgen als erom gevraagd wordt
Een standaard-httpx.Client volgt geen doorverwijzingen. Een 308 komt terug als het antwoord zelf, met een lege response.history en response.next_request ingesteld op het verzoek dat httpx als volgende zou sturen. Geef follow_redirects=True mee en httpx volgt, volgens dezelfde regels voor
De twee bibliotheken zijn het zelfs oneens over de naam van het allow_redirects= van requests aan httpx meegeven is een fout, en de melding wijst naar het juiste woord:
Client.get() got an unexpected keyword argument 'allow_redirects'. Did you mean 'follow_redirects'?
requests beantwoordt de omgekeerde vergissing, follow_redirects=, met het spiegelbeeld van die melding.
client.get(url) met een standaard-httpx.Client krijgt een 308. Wat krijg je terug?
Een standaardtime-out is nog steeds een keuze
httpx begrenst elke aanroep: 5 seconden om te verbinden, 5 voor elke leesactie, 5 voor elke schrijfactie en 5 om te wachten op een vrije verbinding in de pool. Dat is veiliger dan de standaard van requests, eeuwig wachten, maar het is nog steeds een getal dat jij niet hebt gekozen. Deze cursus kiest zijn eigen, HTTPX_TIMEOUT bovenaan side_by_side.py:
HTTPX_TIMEOUT = httpx.Timeout(2.0, connect=1.0)
Dat is 1 seconde om te verbinden en 2 seconden voor elk van de andere drie fasen. Waarom niet het paar van requests, (1.0, 2.0)? httpx accepteert een
client.get(url, timeout=(1.0, 2.0)) in httpx. Wat is er begrensd?
Fouten
De raise_for_status() van httpx is strenger dan die van requests. Hij werpt httpx.HTTPStatusError op voor alles buiten 200 tot en met 299, dus ook een 308 die niet gevolgd is, met een melding die begint met Redirect response '308 Permanent Redirect'. requests laat een 3xx door.
Welke aanroep werpt een exception op bij een 308-antwoord?
De exceptions zelf horen bij een andere familie. Elke exception van requests is een subklasse van OSError, dus except OSError: rond een aanroep van requests vangt zijn time-outs en mislukte verbindingen af. Die van httpx niet: httpx.ReadTimeout is een TimeoutException, die een TransportError is, daarna een RequestError, daarna een httpx.HTTPError, daarna een gewone Exception. Vang de smalste klasse af die past bij wat je wilt afhandelen:
try:
response = client.get(url, timeout=HTTPX_TIMEOUT)
except httpx.TimeoutException:
print("no answer in time")
except httpx.HTTPError: is breder: hij vangt een time-out, een geweigerde verbinding en de HTTPStatusError van raise_for_status() allemaal af.
Een aanroep van httpx staat binnen try met except OSError:. De server antwoordt nooit. Wat gebeurt er?
httpx heeft ook een AsyncClient voor programma’s die geschreven zijn met async en await. Deze cursus gebruikt die niet.
Je opdracht
In side_by_side.py:
who_am_i_httpx(base_url, user, password, *, client, timeout=HTTPX_TIMEOUT)doet watwho_am_idoet, op de httpx-client die hij krijgt:POST base_url + "/login"metauth=(user, password),raise_for_status(),GET base_url + "/me", en deuserteruggeven, mettimeout=timeoutbij beide aanroepen. Inloggegevens als gewone tekst zijn hier prima, omdat httpx ze als UTF-8 codeert.trail_httpx(url, *, client=None, timeout=HTTPX_TIMEOUT)stuurt één GET metfollow_redirects=Trueentimeout=timeout, en geeftredirect_trail(response)terug. Gebruikclient = httpx if client is None else client. Jeredirect_trailwerkt ongewijzigd op een antwoord van httpx, omdat dat ookstatus_code,urlenhistoryheeft.
Voer daarna uit:
python pl_http.py httpx
Eerst laat het zien wat een standaardclient met het oude pad doet, voordat jouw code draait:
--- pl_http's own httpx client.get() of /v0/books/2?x=1, without follow_redirects ---
status_code: 308
history: []
next_request: 'http://books.test/books/2?x=1'
Daarna volgt je trail_httpx het, en de regels komen precies overeen met het requests-spoor uit les 2:
--- your trail_httpx() of /v0/books/2?x=1 ---
value: ['308 http://books.test/v0/books/2?x=1', '200 http://books.test/books/2?x=1']
De books.test omdat de client van pl_http elk verzoek via een eigen transport aan je server op deze machine doorgeeft, een onderdeel dat les 4 vervangt door een who_am_i_httpx als zoë, wiens ✓ deze keer niets extra’s nodig heeft.
Klik op Check my work. Les 4 test beide bibliotheken zonder enige server.
Opdracht
Log in en volg een
In side_by_side.py:
who_am_i_httpx(base_url, user, password, *, client, timeout=HTTPX_TIMEOUT)stuurtPOST base_url + "/login"metauth=(user, password)op de client die hij krijgt, roeptraise_for_status()aan op dat antwoord, stuurtGET base_url + "/me"en geeft deuseruit dedaarvan terug. Beide aanroepen geven timeout=timeoutmee.trail_httpx(url, *, client=None, timeout=HTTPX_TIMEOUT)gebruiktclient = httpx if client is None else client, stuurt één GET vanurlmetfollow_redirects=Trueentimeout=timeout, en geeftredirect_trail(response)terug. Roep hier geenraise_for_status()aan.
Het follow_redirects; allow_redirects uit requests is in httpx een httpx.get of httpx.post die hem negeert, laat de controle falen.
In de python pl_http.py httpx zien hoe een standaardclient stopt bij de 308 van een oud pad, en draait daarna je trail_httpx op dat pad en je who_am_i_httpx als zoë.
Klik daarna op Check my work. Die geeft je httpx.HTTPStatusError opwerpen voordat /me gevraagd wordt. trail_httpx moet beide regels van een 308 en het boek waar die naartoe leidt teruggeven, met een client en zonder. Niets uit je terminal wordt beoordeeld.