Pythons Anforderungsbibliothek (Handbuch)
Dierequests
-Bibliothek ist der De-facto-Standard für HTTP-Anforderungen in Python. Es abstrahiert die Komplexität der Anforderung hinter einer schönen, einfachen API, sodass Sie sich auf die Interaktion mit Diensten und den Verbrauch von Daten in Ihrer Anwendung konzentrieren können.
In diesem Artikel werden einige der nützlichsten Funktionen vonrequests
vorgestellt sowie Informationen zum Anpassen und Optimieren dieser Funktionen für verschiedene Situationen, auf die Sie möglicherweise stoßen. Außerdem erfahren Sie, wie Sierequests
effizient verwenden und verhindern, dass Anforderungen an externe Dienste Ihre Anwendung verlangsamen.
In diesem Tutorial erfahren Sie, wie Sie:
-
Make requests mit den gängigsten HTTP-Methoden
-
Customizeind die Header und Daten Ihrer Anforderungen unter Verwendung der Abfragezeichenfolge und des Nachrichtentexts
-
Inspect Daten aus Ihren Anfragen und Antworten
-
Stellen Sieauthenticated Anfragen
-
Configure Ihre Anforderungen, um zu verhindern, dass Ihre Anwendung gesichert oder verlangsamt wird
Obwohl ich versucht habe, so viele Informationen wie möglich anzugeben, um die in diesem Artikel enthaltenen Funktionen und Beispiele zu verstehen, gehe ich von einemverybasic general knowledge of HTTP aus. Trotzdem können Sie vielleicht trotzdem gut mitmachen.
Nachdem dies nicht mehr möglich ist, wollen wir uns ansehen, wie Sierequests
in Ihrer Anwendung verwenden können!
Erste Schritte mitrequests
Beginnen wir mit der Installation derrequests
-Bibliothek. Führen Sie dazu den folgenden Befehl aus:
$ pip install requests
Wenn SiePipenv zum Verwalten von Python-Paketen bevorzugen, können Sie Folgendes ausführen:
$ pipenv install requests
Sobaldrequests
installiert ist, können Sie es in Ihrer Anwendung verwenden. Das Importieren vonrequests
sieht folgendermaßen aus:
import requests
Jetzt, da Sie alle eingerichtet sind, ist es Zeit, Ihre Reise durchrequests
zu beginnen. Ihr erstes Ziel wird sein, zu lernen, wie Sie eineGET
-Anforderung stellen.
Die GET-Anfrage
HTTP methods wieGET
undPOST
bestimmen, welche Aktion Sie ausführen möchten, wenn Sie eine HTTP-Anforderung stellen. NebenGET
undPOST
gibt es noch einige andere gängige Methoden, die Sie später in diesem Lernprogramm verwenden werden.
Eine der häufigsten HTTP-Methoden istGET
. Die MethodeGET
gibt an, dass Sie versuchen, Daten von einer bestimmten Ressource abzurufen oder abzurufen. Rufen Sierequests.get()
auf, um eineGET
-Anforderung zu stellen.
Um dies zu testen, können Sie eineGET
-Anforderung an GitHubsRoot REST API stellen, indem Sieget()
mit der folgenden URL aufrufen:
>>>
>>> requests.get('https://api.github.com')
Herzliche Glückwünsche! Sie haben Ihre erste Anfrage gestellt. Lassen Sie uns etwas tiefer in die Antwort auf diese Anfrage eintauchen.
Die Antwort
AResponse
ist ein leistungsfähiges Objekt zum Überprüfen der Ergebnisse der Anforderung. Lassen Sie uns dieselbe Anforderung erneut stellen, aber speichern Sie diesmal den Rückgabewert in einer Variablen, damit Sie die Attribute und Verhaltensweisen genauer betrachten können:
>>>
>>> response = requests.get('https://api.github.com')
In diesem Beispiel haben Sie den Rückgabewert vonget()
, einer Instanz vonResponse
, erfasst und in einer Variablen namensresponse
gespeichert. Sie können jetztresponse
verwenden, um viele Informationen zu den Ergebnissen IhrerGET
-Anforderung anzuzeigen.
Statuscodes
Die erste Information, die Sie ausResponse
sammeln können, ist der Statuscode. Ein Statuscode informiert Sie über den Status der Anfrage.
Beispielsweise bedeutet der Status eines200 OK
, dass Ihre Anforderung erfolgreich war, während der Status eines404 NOT FOUND
bedeutet, dass die gesuchte Ressource nicht gefunden wurde. Es gibt auchmany other possible status codes, um Ihnen spezifische Einblicke in das zu geben, was mit Ihrer Anfrage passiert ist.
Durch Zugriff auf.status_code
können Sie den vom Server zurückgegebenen Statuscode anzeigen:
>>>
>>> response.status_code
200
.status_code
hat ein200
zurückgegeben, was bedeutet, dass Ihre Anfrage erfolgreich war und der Server mit den von Ihnen angeforderten Daten geantwortet hat.
Manchmal möchten Sie diese Informationen möglicherweise verwenden, um Entscheidungen in Ihrem Code zu treffen:
if response.status_code == 200:
print('Success!')
elif response.status_code == 404:
print('Not Found.')
Wenn der Server mit dieser Logik den Statuscode200
zurückgibt, gibt Ihr ProgrammSuccess!
aus. Wenn das Ergebnis404
ist, druckt Ihr ProgrammNot Found
.
requests
geht noch einen Schritt weiter, um diesen Prozess für Sie zu vereinfachen. Wenn Sie eineResponse
-Instanz in einem bedingten Ausdruck verwenden, wirdTrue
ausgewertet, wenn der Statuscode zwischen200
und400
liegt, andernfallsFalse
.
Daher können Sie das letzte Beispiel vereinfachen, indem Sie die Anweisungif
neu schreiben:
if response:
print('Success!')
else:
print('An error has occurred.')
Technical Detail: DiesesTruth Value Test wird ermöglicht, weil__bool__()
is an overloaded method aufResponse
liegt.
Dies bedeutet, dass das Standardverhalten vonResponse
neu definiert wurde, um den Statuscode bei der Ermittlung des Wahrheitswerts des Objekts zu berücksichtigen.
Beachten Sie, dass diese Methodenot ist und überprüft, ob der Statuscode200
entspricht. Der Grund dafür ist, dass andere Statuscodes im Bereich von200
bis400
, wie204 NO CONTENT
und304 NOT MODIFIED
, ebenfalls als erfolgreich angesehen werden, da sie einige funktionsfähig sind Antwort.
Zum Beispiel zeigt204
an, dass die Antwort erfolgreich war, aber es gibt keinen Inhalt, der im Nachrichtentext zurückgegeben werden kann.
Stellen Sie daher sicher, dass Sie diese praktische Abkürzung nur verwenden, wenn Sie wissen möchten, ob die Anforderung im Allgemeinen erfolgreich war, und behandeln Sie die Antwort gegebenenfalls entsprechend dem Statuscode entsprechend.
Angenommen, Sie möchten den Statuscode der Antwort in einerif
-Anweisung nicht überprüfen. Stattdessen möchten Sie eine Ausnahme auslösen, wenn die Anforderung nicht erfolgreich war. Sie können dies mit.raise_for_status()
tun:
import requests
from requests.exceptions import HTTPError
for url in ['https://api.github.com', 'https://api.github.com/invalid']:
try:
response = requests.get(url)
# If the response was successful, no Exception will be raised
response.raise_for_status()
except HTTPError as http_err:
print(f'HTTP error occurred: {http_err}') # Python 3.6
except Exception as err:
print(f'Other error occurred: {err}') # Python 3.6
else:
print('Success!')
Wenn Sie.raise_for_status()
aufrufen, wird für bestimmte Statuscodes einHTTPError
ausgelöst. Wenn der Statuscode eine erfolgreiche Anforderung anzeigt, wird das Programm fortgesetzt, ohne dass diese Ausnahme ausgelöst wird.
Further Reading: Wenn Sie mitf-stringsvon Python 3.6 nicht vertraut sind, empfehlen wir Ihnen, diese zu nutzen, da sie eine großartige Möglichkeit sind, Ihre formatierten Zeichenfolgen zu vereinfachen.
Jetzt wissen Sie viel darüber, wie Sie mit dem Statuscode der Antwort umgehen müssen, die Sie vom Server erhalten haben. Wenn Sie jedoch eineGET
-Anforderung stellen, ist Ihnen selten nur der Statuscode der Antwort wichtig. Normalerweise möchten Sie mehr sehen. Als Nächstes sehen Sie, wie Sie die tatsächlichen Daten anzeigen, die der Server im Hauptteil der Antwort zurückgesendet hat.
Inhalt
Die Antwort einerGET
-Anforderung enthält häufig einige wertvolle Informationen, die als Nutzdaten bezeichnet werden, im Nachrichtentext. Mit den Attributen und Methoden vonResponse
können Sie die Nutzlast in verschiedenen Formaten anzeigen.
Um den Inhalt der Antwort inbytes
anzuzeigen, verwenden Sie.content
:
>>>
>>> response = requests.get('https://api.github.com')
>>> response.content
b'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'
Während Sie mit.content
auf die Rohbytes der Antwortnutzdaten zugreifen können, möchten Sie diese häufig mit einer Zeichencodierung wieUTF-8 instring konvertieren. response
erledigt das für Sie, wenn Sie auf.text
zugreifen:
>>>
>>> response.text
'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'
Da für die Dekodierung vonbytes
zustr
ein Kodierungsschema erforderlich ist, versuchtrequests
, dieencoding basierend auf denheaders der Antwort zu erraten, wenn Sie dies nicht angeben ein. Sie können eine explizite Codierung bereitstellen, indem Sie.encoding
festlegen, bevor Sie auf.text
zugreifen:
>>>
>>> response.encoding = 'utf-8' # Optional: requests infers this internally
>>> response.text
'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'
Wenn Sie sich die Antwort ansehen, werden Sie feststellen, dass es sich tatsächlich um serialisierten JSON-Inhalt handelt. Um ein Wörterbuch zu erhalten, können Sie diestr
, die Sie aus.text
abgerufen haben, mitjson.loads()
deserialisieren. Eine einfachere Möglichkeit, diese Aufgabe auszuführen, ist die Verwendung von.json()
:
>>>
>>> response.json()
{'current_user_url': 'https://api.github.com/user', 'current_user_authorizations_html_url': 'https://github.com/settings/connections/applications{/client_id}', 'authorizations_url': 'https://api.github.com/authorizations', 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}', 'commit_search_url': 'https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}', 'emails_url': 'https://api.github.com/user/emails', 'emojis_url': 'https://api.github.com/emojis', 'events_url': 'https://api.github.com/events', 'feeds_url': 'https://api.github.com/feeds', 'followers_url': 'https://api.github.com/user/followers', 'following_url': 'https://api.github.com/user/following{/target}', 'gists_url': 'https://api.github.com/gists{/gist_id}', 'hub_url': 'https://api.github.com/hub', 'issue_search_url': 'https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}', 'issues_url': 'https://api.github.com/issues', 'keys_url': 'https://api.github.com/user/keys', 'notifications_url': 'https://api.github.com/notifications', 'organization_repositories_url': 'https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}', 'organization_url': 'https://api.github.com/orgs/{org}', 'public_gists_url': 'https://api.github.com/gists/public', 'rate_limit_url': 'https://api.github.com/rate_limit', 'repository_url': 'https://api.github.com/repos/{owner}/{repo}', 'repository_search_url': 'https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}', 'current_user_repositories_url': 'https://api.github.com/user/repos{?type,page,per_page,sort}', 'starred_url': 'https://api.github.com/user/starred{/owner}{/repo}', 'starred_gists_url': 'https://api.github.com/gists/starred', 'team_url': 'https://api.github.com/teams', 'user_url': 'https://api.github.com/users/{user}', 'user_organizations_url': 'https://api.github.com/user/orgs', 'user_repositories_url': 'https://api.github.com/users/{user}/repos{?type,page,per_page,sort}', 'user_search_url': 'https://api.github.com/search/users?q={query}{&page,per_page,sort,order}'}
type
des Rückgabewerts von.json()
ist ein Wörterbuch, sodass Sie per Schlüssel auf Werte im Objekt zugreifen können.
Mit Statuscodes und Nachrichtentexten können Sie viel anfangen. Wenn Sie jedoch weitere Informationen benötigen, z. B. Metadaten zur Antwort selbst, müssen Sie sich die Header der Antwort ansehen.
Überschriften
Die Antwortheader können nützliche Informationen enthalten, z. B. den Inhaltstyp der Antwortnutzlast und ein Zeitlimit für die Zwischenspeicherung der Antwort. Um diese Header anzuzeigen, greifen Sie auf.headers
zu:
>>>
>>> response.headers
{'Server': 'GitHub.com', 'Date': 'Mon, 10 Dec 2018 17:49:54 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Status': '200 OK', 'X-RateLimit-Limit': '60', 'X-RateLimit-Remaining': '59', 'X-RateLimit-Reset': '1544467794', 'Cache-Control': 'public, max-age=60, s-maxage=60', 'Vary': 'Accept', 'ETag': 'W/"7dc470913f1fe9bb6c7355b50a0737bc"', 'X-GitHub-Media-Type': 'github.v3; format=json', 'Access-Control-Expose-Headers': 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type', 'Access-Control-Allow-Origin': '*', 'Strict-Transport-Security': 'max-age=31536000; includeSubdomains; preload', 'X-Frame-Options': 'deny', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Referrer-Policy': 'origin-when-cross-origin, strict-origin-when-cross-origin', 'Content-Security-Policy': "default-src 'none'", 'Content-Encoding': 'gzip', 'X-GitHub-Request-Id': 'E439:4581:CF2351:1CA3E06:5C0EA741'}
.headers
gibt ein wörterbuchähnliches Objekt zurück, mit dem Sie per Schlüssel auf Header-Werte zugreifen können. Um beispielsweise den Inhaltstyp der Antwortnutzlast anzuzeigen, können Sie aufContent-Type
zugreifen:
>>>
>>> response.headers['Content-Type']
'application/json; charset=utf-8'
Dieses wörterbuchartige Header-Objekt hat jedoch etwas Besonderes. Die HTTP-Spezifikation definiert Header so, dass die Groß- und Kleinschreibung nicht berücksichtigt wird. Dies bedeutet, dass wir auf diese Header zugreifen können, ohne uns um ihre Großschreibung kümmern zu müssen:
>>>
>>> response.headers['content-type']
'application/json; charset=utf-8'
Unabhängig davon, ob Sie den Schlüssel'content-type'
oder'Content-Type'
verwenden, erhalten Sie den gleichen Wert.
Jetzt haben Sie die Grundlagen zuResponse
gelernt. Sie haben die nützlichsten Attribute und Methoden in Aktion gesehen. Machen wir einen Schritt zurück und sehen, wie sich Ihre Antworten ändern, wenn Sie die Anforderungen vonGET
anpassen.
Parameter für Abfragezeichenfolgen
Eine übliche Methode zum Anpassen der Anforderung vonGET
besteht darin, Werte über die Parameter vonquery stringin der URL zu übergeben. Dazu übergeben Sie mitget()
Daten anparams
. Sie können beispielsweise dieSearch-API von GitHub verwenden, um nach derrequests
-Bibliothek zu suchen:
import requests
# Search GitHub's repositories for requests
response = requests.get(
'https://api.github.com/search/repositories',
params={'q': 'requests+language:python'},
)
# Inspect some attributes of the `requests` repository
json_response = response.json()
repository = json_response['items'][0]
print(f'Repository name: {repository["name"]}') # Python 3.6+
print(f'Repository description: {repository["description"]}') # Python 3.6+
Durch Übergeben des Wörterbuchs{'q': 'requests+language:python'}
an den Parameterparams
von.get()
können Sie die Ergebnisse ändern, die von der Such-API zurückgegeben werden.
Sie könnenparams
anget()
in Form eines Wörterbuchs übergeben, wie Sie es gerade getan haben, oder als Liste von Tupeln:
>>>
>>> requests.get(
... 'https://api.github.com/search/repositories',
... params=[('q', 'requests+language:python')],
... )
Sie können die Werte sogar alsbytes
übergeben:
>>>
>>> requests.get(
... 'https://api.github.com/search/repositories',
... params=b'q=requests+language:python',
... )
Abfragezeichenfolgen sind nützlich, um die Anforderungen vonGET
zu parametrisieren. Sie können Ihre Anforderungen auch anpassen, indem Sie die von Ihnen gesendeten Header hinzufügen oder ändern.
Header anfordern
Um Header anzupassen, übergeben Sie ein Wörterbuch mit HTTP-Headern anget()
mit dem Parameterheaders
. Sie können beispielsweise Ihre vorherige Suchanforderung ändern, um übereinstimmende Suchbegriffe in den Ergebnissen hervorzuheben, indem Sie den Medientyptext-match
in der KopfzeileAccept
angeben:
import requests
response = requests.get(
'https://api.github.com/search/repositories',
params={'q': 'requests+language:python'},
headers={'Accept': 'application/vnd.github.v3.text-match+json'},
)
# View the new `text-matches` array which provides information
# about your search term within the results
json_response = response.json()
repository = json_response['items'][0]
print(f'Text matches: {repository["text_matches"]}')
Der HeaderAccept
teilt dem Server mit, welche Inhaltstypen Ihre Anwendung verarbeiten kann. In diesem Fall verwenden Sie, da Sie erwarten, dass die übereinstimmenden Suchbegriffe hervorgehoben werden, den Headerwertapplication/vnd.github.v3.text-match+json
, einen proprietären GitHubAccept
-Header, bei dem der Inhalt ein spezielles JSON-Format hat.
Bevor Sie weitere Möglichkeiten zum Anpassen von Anforderungen kennenlernen, erweitern wir den Horizont, indem wir andere HTTP-Methoden untersuchen.
Andere HTTP-Methoden
NebenGET
umfassen andere beliebte HTTP-MethodenPOST
,PUT
,DELETE
,HEAD
,PATCH
undOPTIONS
. requests
bietet für jede dieser HTTP-Methoden eine Methode mit einer ähnlichen Signatur wieget()
:
>>>
>>> requests.post('https://httpbin.org/post', data={'key':'value'})
>>> requests.put('https://httpbin.org/put', data={'key':'value'})
>>> requests.delete('https://httpbin.org/delete')
>>> requests.head('https://httpbin.org/get')
>>> requests.patch('https://httpbin.org/patch', data={'key':'value'})
>>> requests.options('https://httpbin.org/get')
Jeder Funktionsaufruf sendet eine Anforderung an den Diensthttpbin
unter Verwendung der entsprechenden HTTP-Methode. Für jede Methode können Sie ihre Antworten auf dieselbe Weise wie zuvor überprüfen:
>>>
>>> response = requests.head('https://httpbin.org/get')
>>> response.headers['Content-Type']
'application/json'
>>> response = requests.delete('https://httpbin.org/delete')
>>> json_response = response.json()
>>> json_response['args']
{}
Header, Antwortkörper, Statuscodes und mehr werden für jede Methode inResponse
zurückgegeben. Als Nächstes sehen Sie sich die MethodenPOST
,PUT
undPATCH
genauer an und erfahren, wie sie sich von den anderen Anforderungstypen unterscheiden.
Der Nachrichtentext
Gemäß der HTTP-Spezifikation leitenPOST
,PUT
und die weniger häufigenPATCH
-Anforderungen ihre Daten über den Nachrichtentext und nicht über Parameter in der Abfragezeichenfolge weiter. Mitrequests
übergeben Sie die Nutzdaten an dendata
-Parameter der entsprechenden Funktion.
data
verwendet ein Wörterbuch, eine Liste von Tupeln, Bytes oder ein dateiähnliches Objekt. Sie möchten die Daten, die Sie im Hauptteil Ihrer Anfrage senden, an die spezifischen Anforderungen des Dienstes anpassen, mit dem Sie interagieren.
Wenn der Inhaltstyp Ihrer Anfrage beispielsweiseapplication/x-www-form-urlencoded
ist, können Sie die Formulardaten als Wörterbuch senden:
>>>
>>> requests.post('https://httpbin.org/post', data={'key':'value'})
Sie können dieselben Daten auch als Liste von Tupeln senden:
>>>
>>> requests.post('https://httpbin.org/post', data=[('key', 'value')])
Wenn Sie jedoch JSON-Daten senden müssen, können Sie den Parameterjson
verwenden. Wenn Sie JSON-Daten überjson
übergeben, serialisiertrequests
Ihre Daten und fügt den richtigenContent-Type
-Header für Sie hinzu.
httpbin.org ist eine großartige Ressource, die vom Autor vonrequests
,Kenneth Reitz erstellt wurde. Es ist ein Dienst, der Testanforderungen akzeptiert und mit Daten zu den Anforderungen antwortet. Sie können es beispielsweise verwenden, um die Anforderung eines einfachenPOST
zu überprüfen:
>>>
>>> response = requests.post('https://httpbin.org/post', json={'key':'value'})
>>> json_response = response.json()
>>> json_response['data']
'{"key": "value"}'
>>> json_response['headers']['Content-Type']
'application/json'
Sie können der Antwort entnehmen, dass der Server Ihre Anforderungsdaten und Header beim Senden empfangen hat. requests
stellt Ihnen diese Informationen auch in Form vonPreparedRequest
zur Verfügung.
Überprüfen Sie Ihre Anfrage
Wenn Sie eine Anfrage stellen, bereitet die Bibliothek vonrequests
die Anfrage vor, bevor sie tatsächlich an den Zielserver gesendet wird. Die Anforderungsvorbereitung umfasst Dinge wie das Überprüfen von Headern und das Serialisieren von JSON-Inhalten.
Sie können diePreparedRequest
anzeigen, indem Sie auf.request
zugreifen:
>>>
>>> response = requests.post('https://httpbin.org/post', json={'key':'value'})
>>> response.request.headers['Content-Type']
'application/json'
>>> response.request.url
'https://httpbin.org/post'
>>> response.request.body
b'{"key": "value"}'
Durch Überprüfen derPreparedRequest
erhalten Sie Zugriff auf alle Arten von Informationen über die angeforderte Anforderung, z. B. Nutzdaten, URL, Header, Authentifizierung und mehr.
Bisher haben Sie viele verschiedene Arten von Anfragen gestellt, aber alle hatten eines gemeinsam: Es handelt sich um nicht authentifizierte Anfragen an öffentliche APIs. Bei vielen Diensten, auf die Sie möglicherweise stoßen, möchten Sie, dass Sie sich auf irgendeine Weise authentifizieren.
Authentifizierung
Die Authentifizierung hilft einem Dienst zu verstehen, wer Sie sind. In der Regel geben Sie Ihre Anmeldeinformationen an einen Server weiter, indem Sie Daten über den HeaderAuthorization
oder einen vom Dienst definierten benutzerdefinierten Header übergeben. Alle Anforderungsfunktionen, die Sie bisher gesehen haben, bieten einen Parameter namensauth
, mit dem Sie Ihre Anmeldeinformationen übergeben können.
Ein Beispiel für eine API, die eine Authentifizierung erfordert, ist dieAuthenticated User-API von GitHub. Dieser Endpunkt enthält Informationen zum Profil des authentifizierten Benutzers. Um eine Anfrage an die API für authentifizierte Benutzer zu stellen, können Sie Ihren GitHub-Benutzernamen und Ihr Kennwort in einem Tupel anget()
übergeben:
>>>
>>> from getpass import getpass
>>> requests.get('https://api.github.com/user', auth=('username', getpass()))
Die Anforderung war erfolgreich, wenn die Anmeldeinformationen, die Sie im Tupel anauth
übergeben haben, gültig sind. Wenn Sie versuchen, diese Anforderung ohne Anmeldeinformationen zu stellen, wird der Statuscode401 Unauthorized
lauten:
>>>
>>> requests.get('https://api.github.com/user')
Wenn Sie Ihren Benutzernamen und Ihr Kennwort in einem Tupel an den Parameterauth
übergeben, wendetrequests
die Anmeldeinformationen mithilfe derBasic access authentication scheme von HTTP unter der Haube an.
Daher können Sie dieselbe Anforderung stellen, indem Sie explizite Anmeldeinformationen für die Standardauthentifizierung mitHTTPBasicAuth
übergeben:
>>>
>>> from requests.auth import HTTPBasicAuth
>>> from getpass import getpass
>>> requests.get(
... 'https://api.github.com/user',
... auth=HTTPBasicAuth('username', getpass())
... )
Obwohl Sie für die Standardauthentifizierung nicht explizit sein müssen, möchten Sie sich möglicherweise mit einer anderen Methode authentifizieren. requests
bietet standardmäßige andere Authentifizierungsmethoden wieHTTPDigestAuth
undHTTPProxyAuth
.
Sie können sogar Ihren eigenen Authentifizierungsmechanismus bereitstellen. Dazu müssen Sie zunächst eine Unterklasse vonAuthBase
erstellen. Dann implementieren Sie__call__()
:
import requests
from requests.auth import AuthBase
class TokenAuth(AuthBase):
"""Implements a custom authentication scheme."""
def __init__(self, token):
self.token = token
def __call__(self, r):
"""Attach an API token to a custom auth header."""
r.headers['X-TokenAuth'] = f'{self.token}' # Python 3.6+
return r
requests.get('https://httpbin.org/get', auth=TokenAuth('12345abcde-token'))
Hier empfängt der Mechanismus Ihres benutzerdefiniertenTokenAuth
ein Token und nimmt dieses Token dann in den Header vonX-TokenAuth
Ihrer Anfrage auf.
Schlechte Authentifizierungsmechanismen können zu Sicherheitslücken führen. Wenn für einen Dienst aus irgendeinem Grund kein benutzerdefinierter Authentifizierungsmechanismus erforderlich ist, sollten Sie immer ein bewährtes Authentifizierungsschema wie Basic oder OAuth verwenden.
Wenn Sie über Sicherheit nachdenken, sollten Sie den Umgang mit SSL-Zertifikaten mitrequests
in Betracht ziehen.
Überprüfung des SSL-Zertifikats
Jedes Mal, wenn die Daten, die Sie senden oder empfangen möchten, vertraulich sind, ist die Sicherheit wichtig. Die Art und Weise, wie Sie mit sicheren Sites über HTTP kommunizieren, besteht darin, eine verschlüsselte Verbindung mit SSL herzustellen. Daher ist die Überprüfung des SSL-Zertifikats des Zielservers von entscheidender Bedeutung.
Die gute Nachricht ist, dassrequests
dies standardmäßig für Sie erledigt. Es gibt jedoch einige Fälle, in denen Sie dieses Verhalten möglicherweise ändern möchten.
Wenn Sie die Überprüfung des SSL-Zertifikats deaktivieren möchten, übergeben SieFalse
an den Parameterverify
der Anforderungsfunktion:
>>>
>>> requests.get('https://api.github.com', verify=False)
InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
requests
warnt Sie sogar, wenn Sie eine unsichere Anfrage stellen, um Ihre Daten zu schützen!
Note:requests
uses a package called certifi
zur Bereitstellung von Zertifizierungsstellen. Dadurch erfahrenrequests
, welchen Behörden sie vertrauen können. Daher sollten Siecertifi
regelmäßig aktualisieren, um Ihre Verbindungen so sicher wie möglich zu halten.
Performance
Bei der Verwendung vonrequests
, insbesondere in einer Produktionsanwendungsumgebung, ist es wichtig, die Auswirkungen auf die Leistung zu berücksichtigen. Funktionen wie Timeout-Kontrolle, Sitzungen und Wiederholungslimits können Ihnen dabei helfen, dass Ihre Anwendung reibungslos läuft.
Timeouts
Wenn Sie eine Inline-Anfrage an einen externen Dienst stellen, muss Ihr System auf die Antwort warten, bevor Sie fortfahren. Wenn Ihre Anwendung zu lange auf diese Antwort wartet, können Anforderungen an Ihren Dienst gesichert werden, Ihre Benutzererfahrung kann darunter leiden oder Ihre Hintergrundjobs können hängen bleiben.
Standardmäßig wartetrequests
unbegrenzt auf die Antwort. Daher sollten Sie fast immer eine Zeitüberschreitungsdauer angeben, um zu verhindern, dass diese Ereignisse auftreten. Verwenden Sie den Parametertimeout
, um das Zeitlimit der Anforderung festzulegen. timeout
kann eine Ganzzahl oder ein Gleitkommawert sein, der die Anzahl der Sekunden darstellt, die auf eine Antwort gewartet werden muss, bevor eine Zeitüberschreitung auftritt:
>>>
>>> requests.get('https://api.github.com', timeout=1)
>>> requests.get('https://api.github.com', timeout=3.05)
Bei der ersten Anforderung tritt nach 1 Sekunde eine Zeitüberschreitung für die Anforderung auf. Bei der zweiten Anforderung tritt nach 3,05 Sekunden eine Zeitüberschreitung für die Anforderung auf.
You can also pass a tuple bistimeout
, wobei das erste Element ein Verbindungszeitlimit ist (die Zeit, die es dem Client ermöglicht, eine Verbindung zum Server herzustellen) und das zweite ein Lesezeitlimit ist (die Zeit, auf die es wartet eine Antwort, sobald Ihr Client eine Verbindung hergestellt hat):
>>>
>>> requests.get('https://api.github.com', timeout=(2, 5))
Wenn die Anforderung innerhalb von 2 Sekunden eine Verbindung herstellt und innerhalb von 5 Sekunden nach dem Herstellen der Verbindung Daten empfängt, wird die Antwort wie zuvor zurückgegeben. Wenn die Anforderung abgelaufen ist, löst die Funktion eine Ausnahme vonTimeout
aus:
import requests
from requests.exceptions import Timeout
try:
response = requests.get('https://api.github.com', timeout=1)
except Timeout:
print('The request timed out')
else:
print('The request did not time out')
Ihr Programm kann die Ausnahme vonTimeout
abfangen und entsprechend reagieren.
Das Sitzungsobjekt
Bisher haben Sie sich mit APIs auf hoher Ebene fürrequests
wieget()
undpost()
befasst. Diese Funktionen sind Abstraktionen dessen, was passiert, wenn Sie Ihre Anfragen stellen. Sie verbergen Implementierungsdetails wie die Verwaltung von Verbindungen, damit Sie sich keine Sorgen machen müssen.
Unter diesen Abstraktionen befindet sich eine Klasse namensSession
. Wenn Sie Ihre Kontrolle darüber, wie Anforderungen gestellt werden, optimieren oder die Leistung Ihrer Anforderungen verbessern müssen, müssen Sie möglicherweise die InstanzSession
direkt verwenden.
Sitzungen werden verwendet, um Parameter über Anforderungen hinweg beizubehalten. Wenn Sie beispielsweise dieselbe Authentifizierung für mehrere Anforderungen verwenden möchten, können Sie eine Sitzung verwenden:
import requests
from getpass import getpass
# By using a context manager, you can ensure the resources used by
# the session will be released after use
with requests.Session() as session:
session.auth = ('username', getpass())
# Instead of requests.get(), you'll use session.get()
response = session.get('https://api.github.com/user')
# You can inspect the response just like you did before
print(response.headers)
print(response.json())
Jedes Mal, wenn Sie eine Anfrage mitsession
stellen, bleiben die Anmeldeinformationen erhalten, sobald sie mit Authentifizierungsdaten initialisiert wurden.
Die primäre Leistungsoptimierung von Sitzungen erfolgt in Form von dauerhaften Verbindungen. Wenn Ihre App mitSession
eine Verbindung zu einem Server herstellt, bleibt diese Verbindung in einem Verbindungspool erhalten. Wenn Ihre App erneut eine Verbindung zum selben Server herstellen möchte, wird eine Verbindung aus dem Pool wiederverwendet, anstatt eine neue herzustellen.
Max Wiederholungen
Wenn eine Anforderung fehlschlägt, möchten Sie möglicherweise, dass Ihre Anwendung dieselbe Anforderung erneut versucht. requests
erledigt dies jedoch standardmäßig nicht für Sie. Um diese Funktionalität anzuwenden, müssen Sie ein benutzerdefiniertesTransport Adapter implementieren.
Mit Transportadaptern können Sie eine Reihe von Konfigurationen pro Dienst definieren, mit dem Sie interagieren. Angenommen, Sie möchten, dass alle Anforderungen anhttps://api.github.com
dreimal wiederholt werden, bevor schließlichConnectionError
ausgelöst werden. Sie würden einen Transportadapter erstellen, seinen Parametermax_retries
festlegen und ihn in einen vorhandenenSession
einbinden:
import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import ConnectionError
github_adapter = HTTPAdapter(max_retries=3)
session = requests.Session()
# Use `github_adapter` for all requests to endpoints that start with this URL
session.mount('https://api.github.com', github_adapter)
try:
session.get('https://api.github.com')
except ConnectionError as ce:
print(ce)
Wenn SieHTTPAdapter
,github_adapter
ansession
hängen, bleibtsession
bei jeder Anforderung anhttps://api.github.com an der Konfiguration.
Zeitüberschreitungen, Transportadapter und Sitzungen dienen dazu, Ihren Code effizient und Ihre Anwendung stabil zu halten.
Fazit
Sie haben einen langen Weg zurückgelegt, um die leistungsstarkerequests
-Bibliothek von Python kennenzulernen.
Sie können jetzt:
-
Stellen Sie Anforderungen mit verschiedenen HTTP-Methoden wie
GET
,POST
undPUT
-
Passen Sie Ihre Anforderungen an, indem Sie Header, Authentifizierung, Abfragezeichenfolgen und Nachrichtentexte ändern
-
Überprüfen Sie die Daten, die Sie an den Server senden, und die Daten, die der Server an Sie zurücksendet
-
Arbeiten Sie mit der Überprüfung des SSL-Zertifikats
-
Verwenden Sie
requests
effektiv mitmax_retries
,timeout
, Sitzungen und Transportadaptern
Da Sie gelernt haben, wie manrequests
verwendet, können Sie die weite Welt der Webdienste erkunden und mithilfe der faszinierenden Daten, die sie bereitstellen, fantastische Anwendungen erstellen.