Tutoriel sur la librairie requests

La bibliothèque request est le standard de facto pour faire des requêtes HTTP en Python. Elle simplifie les complexités des requêtes derrière une belle API simple pour que vous puissiez vous concentrer sur l'interaction avec les services et la consommation des données dans votre application.

Tout au long de cet article, vous découvrirez quelques-unes des fonctionnalités les plus utiles requests a à offrir ainsi que comment personnaliser et optimiser ces fonctionnalités pour les différentes situations que vous puissiez rencontrer.

Vous apprendrez également à utiliser le requêtage de manière efficace et à éviter que les requêtes adressées à des services externes ne ralentissent votre application.

Dans ce tutoriel, vous apprendrez à :

  • Effectuer des requêtes en utilisant les méthodes HTTP les plus courantes
  • Personnaliser les en-têtes et les données de vos requêtes, en utilisant la chaîne de requête et le corps du message.
  • Inspecter les données de vos demandes et réponses
  • Faire des demandes authentifiées
  • Configurer vos requêtes pour éviter que votre application ne recule ou ne ralentisse.

Bien que j'aie essayé d'inclure autant d'informations que nécessaire pour comprendre les fonctionnalités et les exemples inclus dans cet article, je présuppose une connaissance générale de HTTP très basique. Cela dit, vous pouvez quand même suivre le mouvement de toute façon. (En savoir plus sur http)


Maintenant que c'est terminé, plongeons et voyons comment vous pouvez utiliser requests dans votre application !

Démarrer avec requests

Commençons par installer la bibliothèque de requêtes. Pour ce faire, exécutez la commande suivante :

-----------------------

$pip install requests 

----------------------

Si vous préférez utiliser Pipenv pour gérer les paquets Python, vous pouvez exécuter ce qui suit :

-------------------------------

$pipenv install requests

--------------------------------

Une fois requests installée, vous pouvez l'utiliser dans votre application. L'importation de requests ressemble à ceci :

import requests

Maintenant que vous êtes tous prêts, il est temps de commencer votre voyage à travers les demandes. Votre premier objectif sera d'apprendre à faire une requête GET

Le requêtes get

Deux liens sur les requêtes

Les méthodes HTTP telles que GET et POST, déterminent l'action que vous essayez d'effectuer lorsque vous faites une requête HTTP. Outre GET et POST, il existe plusieurs autres méthodes courantes que vous utiliserez plus tard dans ce tutoriel.

L'une des méthodes HTTP les plus courantes est GET. La méthode GET indique que vous essayez d'obtenir ou de récupérer des données d'une ressource spécifique. Pour faire une requête GET, invoquez :

------------------------

requests.get().

------------------------

Pour tester cela, vous pouvez faire une requête GET à l'API Root REST de GitHub en appelant get() avec l'URL suivante :

-------------------------------------------------

>>> requests.get('https://api.github.com')

<Response [200]>

-------------------------------------------------

Félicitations ! Vous avez fait votre première requête. Plongeons un peu plus profondément dans la réponse à cette demande.

La réponse

Une réponse est un objet puissant pour inspecter les résultats de la requête. 

Faisons la même demande encore une fois, mais cette fois, stockons la valeur de retour dans une variable pour que vous puissiez voir de plus près ses attributs et ses comportements :

---------------------------------------------------------------

>>> response = requests.get('https://api.github.com')

------------------------------------------------------------------

Dans cet exemple, vous avez capturé la valeur de get(), qui est une instance de Response, et l'avez stockée dans une variable appelée response. Vous pouvez maintenant utiliser la réponse pour voir beaucoup d'informations sur les résultats de votre requête GET.

Status Codes

Le premier élément d'information que vous pouvez recueillir à partir de la réponse est le code d'état. Un code de statut vous informe du statut de la demande.

Par exemple, un statut 200 OK signifie que votre demande a été acceptée, alors qu'un statut 404 NOT FOUND signifie que la ressource que vous cherchiez n'a pas été trouvée. 

Une liste des codes et des messages d’erreurs :

[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes,

https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml]

Il existe également de nombreux autres codes d'état possibles pour vous donner un aperçu précis de ce qui s'est passé avec votre demande.

En accédant à .status_code, vous pouvez voir le code d'état que le serveur a renvoyé :

---------------------------------------------

>>> response.status_code

200

-----------------------------------------------

.status_code a retourné un 200, ce qui signifie que votre demande a été acceptée et que le serveur a répondu avec les données que vous demandiez.

Parfois, vous voudrez peut-être utiliser cette nouvelle information pour prendre des décisions dans votre code :

---------------------------------------------------------

if response.status_code == 200:

    print('Success!')


elif response.status_code == 404:

    print('Not Found.')

----------------------------------------------------------

Avec cette logique, si le serveur renvoie un code d'état 200, votre programme affichera Succès !

Si le résultat est un 404, votre programme imprimera Not Found (pas trouvé).

La librairie va plus loin en simplifiant ce processus pour vous.

Si vous utilisez une instance de réponse dans une expression conditionnelle, elle est équivalente à Vrai si le code d'état est compris entre 200 et 400, et Faux sinon.

Par conséquent, vous pouvez simplifier le dernier exemple en écrivant l'instruction if :

----------------------------------------------------------------

if response:

    print('Success!')


else:

    print('An error has occurred.')

-------------------------------------------------------------------


Détail technique : Cette valeur vraie est rendue possible parce que __bool__() est une méthode saturée en réponse.

Cela signifie que le comportement par défaut de Response a été redéfini pour prendre en compte le code d'état lors de la détermination de la valeur de vérité de l'objet.

Gardez à l'esprit que cette méthode ne vérifie pas que le code d'état est égal à 200.

Cela s'explique par le fait que d'autres codes d'état compris entre 200 et 400, tels que 204 NO CONTENT et 304 NOT MODIFIED, sont également considérés comme des succès en ce sens qu'ils fournissent une réponse qui peut fonctionner.

Par exemple, le 204 vous indique que la réponse a réussi, mais il n'y a pas de contenu à retourner dans le corps du message.

Par conséquent, assurez-vous d'utiliser cette abréviation  uniquement si vous voulez savoir si la demande a été généralement acceptée et, si nécessaire, traitez la réponse de façon appropriée en fonction du code d'état.

Supposons que vous ne vouliez pas vérifier le code de statut de la réponse dans une instruction if.

Au lieu de cela, si vous souhaitez lever une exception si la demande a échoué. Vous pouvez le faire en utilisant la commande .raise_for_status() :

--------------------------------------------------------------------------------------

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!')

--------------------------------------------------------------------------------------------------

Si vous invoquez .raise_for_status(), une erreur HTTPError sera levée pour certains codes de statut.

Si le code d'état (status code) indique que la demande a été acceptée, le programme se poursuivra sans que cette exception soit levée.

Maintenant, vous en savez beaucoup sur la façon de gérer le code d'état de la réponse que vous avez reçue du serveur.

Cependant, lorsque vous faites une requête GET, vous vous souciez rarement uniquement du code d'état de la réponse. D'habitude, vous voulez en voir plus.

 Ensuite, vous verrez comment afficher les données réelles que le serveur a renvoyées dans le corps de la réponse.

Contenu

La réponse d'une requête GET contient souvent des informations précieuses, connues sous le nom de payload, dans le corps du message.

En utilisant les attributs et les méthodes de réponse, vous pouvez visualiser la payload dans une variété de formats différents.

Pour voir le contenu de la réponse en octets, vous utilisez.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}"}'


----------------------------------------------------------------------

Alors que .content vous donne accès aux octets bruts de la réponse, vous voudrez souvent les convertir en chaîne de caractères en utilisant un codage de caractères tel que UTF-8. response le fera pour vous lorsque vous accédez à .text :

-------------------------------------------------------------------------------------------------

>>> 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}"}'


----------------------------------------------------------------------------------------

Comme le décodage des octets d'une chaîne nécessite un schéma d'encodage, les requêtes tenteront de deviner l'encodage en fonction des en-têtes de la réponse si vous n'en spécifiez pas un. Vous pouvez fournir un encodage explicite en paramétrant .encoding avant d'accéder à .text :

--------------------------------------------------------------

>>> 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}"}'


------------------------------------------------------------------------------

Si vous regardez la réponse, vous verrez qu'il s'agit en fait d'un contenu JSON sérialisé.

Pour obtenir un dictionnaire, vous pouvez prendre la chaîne que vous avez récupérée de .text et la désérialiser en utilisant json.loads(). 

Cependant, un moyen plus simple d'accomplir cette tâche est d'utiliser .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}'}

---------------------------------------------------

Le type de la valeur de retour de.json() est un dictionnaire, vous pouvez donc accéder aux valeurs de l'objet par clé.

Vous pouvez faire beaucoup avec les codes de statut et les corps de message.

Mais, si vous avez besoin de plus d'informations, comme des métadonnées sur la réponse elle-même, vous devrez regarder les en-têtes de la réponse.

Headers (en-têtes)

Les en-têtes de réponse peuvent vous fournir des informations utiles, telles que le type de contenu de la charge de la réponse et une limite de temps sur la durée de mise en cache de la réponse. 

Pour afficher ces en-têtes, accédez à .headers :

-------------------------------------------------------------

>>> 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 retourne un objet de type dictionnaire, vous permettant d'accéder aux valeurs d'en-tête par clé. Par exemple, pour voir le type de contenu de la charge utile de réponse, vous pouvez accéder au type de contenu :

---------------------------------------------------

>>> response.headers['Content-Type']

'application/json; charset=utf-8'

------------------------------------------------------

Il y a quelque chose de spécial à propos de cet objet d'en-tête semblable à un dictionnaire.

La spécification HTTP définit les en-têtes comme étant insensibles à la casse, ce qui signifie que nous pouvons accéder à ces en-têtes sans nous soucier de leur capitalisation :

------------------------------------------------------

>>> response.headers['content-type']

'application/json; charset=utf-8'

------------------------------------------------------

Que vous utilisiez la clé'Content-type' ou'Content-Type', vous obtiendrez la même valeur.

Maintenant, vous avez appris les bases de Response.

 Vous avez vu ses attributs et méthodes les plus utiles en action. Prenons un peu de recul et voyons comment vos réponses changent lorsque vous personnalisez vos requêtes GET.

Paramètres de chaîne de requête

Une façon courante de personnaliser une requête GET est de passer les valeurs par les paramètres de chaîne de requête dans l'URL.

Pour ce faire en utilisant get(), vous passez les données aux params. Par exemple, vous pouvez utiliser l'API de recherche de GitHub pour rechercher la bibliothèque de requêtes :

---------------------------------------------------------------------------

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+


------------------------------------------------------------------

En passant le dictionnaire

{'q': 'requests+language:python'} au paramètre params de .get(), vous pouvez modifier les résultats qui reviennent de l'API de recherche.

Vous pouvez passer les paramètres à get() sous la forme d'un dictionnaire, comme vous venez de le faire, ou d'une liste de tuples :

---------------------------------------------------------------------------


>>> requests.get(

...    'https://api.github.com/search/repositories',

...    params=[('q', 'requests+language:python')],

... )

<Response [200]>


-------------------------------------------------------------------------------

You can even pass the values as bytes:

-------------------------------------------------------------------------------

>>> requests.get(

...    'https://api.github.com/search/repositories',

...    params=b'q=requests+language:python',

... )

<Response [200]>

----------------------------------------------------------------------

Les chaînes de requête sont utiles pour paramétrer les requêtes GET. Vous pouvez également personnaliser vos demandes en ajoutant ou modifiant les en-têtes que vous envoyez.

Request Headers

Pour personnaliser les en-têtes, vous passez un dictionnaire d'en-têtes HTTP à get() en utilisant le paramètre headers.

Par exemple, vous pouvez modifier votre demande de recherche précédente pour mettre en évidence les termes de recherche correspondants dans les résultats en spécifiant le type de support de texte correspondant dans l'en-tête Accepter :

---------------------------------------------------------------------------------

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"]}')


----------------------------------------------------------------------------------


L'en-tête accept indique au serveur quels types de contenu votre application peut gérer.

Dans ce cas, puisque vous vous attendez à ce que les termes de recherche correspondants soient mis en évidence, vous utilisez la valeur d'en-tête application/vnd.github.v3.text-match+json, qui est bien un en-tête propriétaire GitHub soumis à l’acceptation où le contenu est un format particulier JSON.

Avant d'apprendre d'autres façons de personnaliser les requêtes, élargissons l'horizon en explorant d'autres méthodes HTTP.

Autres méthodes HTTP

En plus de GET, d'autres méthodes HTTP populaires incluent POST, PUT, DELETE, HEAD, PATCH et OPTIONS. requests fournit une méthode, avec une signature similaire à get(), pour chacune de ces méthodes HTTP :

------------------------------------------------------------------------------------------------

>>> 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')


------------------------------------------------------------------------------------------------

Chaque appel de fonction fait une requête au service httpbin en utilisant la méthode HTTP correspondante.

 Pour chaque méthode, vous pouvez inspecter leurs réponses de la même manière que vous l'avez fait auparavant :

---------------------------------------------------------------------

>>> 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']

{}

------------------------------------------------------------------------

Les en-têtes, les corps de réponse, les codes d'état et autres sont retournés dans la réponse pour chaque méthode. 

Ensuite, vous examinerez de plus près les méthodes POST, PUT et PATCH et apprendrez en quoi elles diffèrent des autres types de requêtes.

Le corps du message

Selon la spécification HTTP, les requêtes POST, PUT et les requêtes PATCH moins courantes transmettent leurs données par le corps du message plutôt que par les paramètres de la chaîne de requête. 

En utilisant les requêtes, vous passerez payload au paramètre de données de la fonction correspondante.

Les données prennent la forme d'un dictionnaire, d'une liste de tuples, d'octets (byte) ou d'un objet de type fichier. Vous devrez adapter les données que vous envoyez dans le corps de votre demande aux besoins spécifiques du service avec lequel vous interagissez.

Par exemple, si le type de contenu de votre demande est application/x-www-form-urlencoded, vous pouvez envoyer les données du formulaire comme dictionnaire :

---------------------------------------------------------------------------------------


>>> requests.post('https://httpbin.org/post', data={'key':'value'})

<Response [200]>


You can also send that same data as a list of tuples:

>>> requests.post('https://httpbin.org/post', data=[('key', 'value')])

<Response [200]>


-------------------------------------------------------------------------------------------

Si, toutefois, vous devez envoyer des données JSON, vous pouvez utiliser le paramètre json. Lorsque vous passez des données JSON via json, les requêtes sérialiseront vos données et ajouteront l'en-tête Content-Type correct pour vous.

httpbin.org est une excellente ressource créée par l'auteur des requêtes, Kenneth Reitz.

Il s'agit d'un service qui accepte les demandes de test et répond avec des données sur les demandes. Par exemple, vous pouvez l'utiliser pour inspecter une requête POST de base :

----------------------------------------------------

>>> 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'

------------------------------------------------------------

Vous pouvez voir d'après la réponse que le serveur a reçu les données et les en-têtes de votre demande au fur et à mesure que vous les envoyez.

Requests vous fournit également ces informations sous la forme d'une PreparedRequest.

Inspecter les requêtes

Lorsque vous faites une requête, la librairie requests prépare la requête avant de l'envoyer au serveur de destination.

La préparation des demandes comprend des choses comme la validation des en-têtes et la sérialisation du contenu JSON.

Vous pouvez visualiser la PreparedRequest en accédant à .request :

-------------------------------------------------

>>> 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"}'


--------------------------------------

Inspecter la PreparedRequest vous donne accès à toutes sortes d'informations sur la demande en cours, telles que la charge utile, l'URL, les en-têtes, l'authentification, etc.

Jusqu'à présent, vous avez fait beaucoup de types de requêtes différentes, mais elles ont toutes une chose en commun : ce sont des requêtes non authentifiées aux API publiques.

De nombreux services que vous rencontrerez peut-être voudront que vous vous authentifiez d'une façon ou d'une autre.

Authentification

L'authentification aide un service à comprendre qui vous êtes.

Généralement, vous fournissez vos informations d'identification à un serveur en passant les données par l'en-tête d'autorisation ou un en-tête personnalisé défini par le service.

Toutes les fonctions de requête que vous avez vues jusqu'à présent fournissent un paramètre appelé auth, qui vous permet de passer vos identifiants.

Un exemple d'API nécessitant une authentification est l'API Utilisateur Authentifié de GitHub. Ce point final fournit des informations sur le profil de l'utilisateur authentifié.

Pour faire une demande à l'API Utilisateur Authentifié, vous pouvez passer votre nom d'utilisateur et mot de passe GitHub dans un tuple pour obtenir() :

-----------------------------------------------------------------------

>>> from getpass import getpass

>>> requests.get('https://api.github.com/user', auth=('username', getpass()))

<Response [200]>

La requête a réussi si les informations d'identification que vous avez passées dans le tuple à auth sont valides. Si vous essayez de faire cette demande sans justificatif d'identité, vous verrez que le code d'état est 401 Unauthorized :

>>> requests.get('https://api.github.com/user')

<Response [401]>

------------------------------------------------------------------------

Lorsque vous passez votre nom d'utilisateur et votre mot de passe dans un tuple au paramètre auth, requests applique les informations d'identification en utilisant le schéma d'authentification d'accès HTTP de base sous le capot.

Par conséquent, vous pouvez faire la même requête en passant les informations d'authentification de base explicites en utilisant HTTPBasicAuth :

-------------------------------------------------------------------------

>>> from requests.auth import HTTPBasicAuth

>>> from getpass import getpass

>>> requests.get(

...    'https://api.github.com/user',

...    auth=HTTPBasicAuth('username', getpass())

... )

<Response [200]>


-------------------------------------------------------------------

Bien que vous n'ayez pas besoin d'être explicite pour l'authentification de base, vous pouvez utiliser une autre méthode d'authentification.

fournit d'autres méthodes d'authentification prêtes à l'emploi telles que HTTPDigestAuth et HTTPProxyAuth.

Vous pouvez même fournir votre propre mécanisme d'authentification. Pour ce faire, vous devez d'abord créer une sous-classe de AuthBase. Ensuite, vous implémentez __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'))

------------------------------------------------

Ici, votre mécanisme TokenAuth personnalisé reçoit un jeton, puis inclut ce jeton dans l'en-tête X-TokenAuth de votre requête.

De mauvais mécanismes d'authentification peuvent entraîner des vulnérabilités de sécurité, donc à moins qu'un service ne nécessite un mécanisme d'authentification personnalisé pour une raison quelconque, vous voudrez toujours utiliser un schéma d'authentification éprouvé comme Basic ou OAuth.

Pendant que vous pensez à la sécurité, envisageons de traiter les certificats SSL en utilisant requests.

Vérification de certificat ssl

Chaque fois que les données que vous essayez d'envoyer ou de recevoir sont sensibles, la sécurité est importante. La façon dont vous communiquez avec les sites sécurisés par HTTP est d'établir une connexion cryptée en utilisant SSL, ce qui signifie que la vérification du certificat SSL du serveur cible est essentielle.

La bonne nouvelle, c'est que requests le fait pour vous par défaut. Cependant, il y a quelques cas où vous pourriez vouloir changer ce comportement.

Si vous voulez désactiver la vérification du certificat SSL, vous passez False au paramètre verify de la fonction request :

------------------------------------------
>>> requests.get('https://api.github.com', verify=False)

--------------------------------------------

InsecureRequestWarning : Une demande HTTPS non vérifiée est en cours. L'ajout de la vérification des certificats est fortement conseillé. Tu vois :

------------------------------------------------------

https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings

  InsecureRequestWarning)

<Response [200]>

------------------------------------------------------

vous avertit même lorsque vous faites une demande non sécurisée pour vous aider à protéger vos données !

Remarque : requests utilise un paquet appelé certifi pour fournir les normes de certification. Cela permet aux demandes de savoir à quelles normes elles peuvent faire confiance. Par conséquent, vous devriez mettre à jour votre certificat fréquemment afin de garder vos connexions aussi sécurisées que possible.

Gestion de la performance

Lorsque vous requests, en particulier dans un environnement d'application de production, il est important de prendre en compte les implications en termes de performances.

Des fonctions telles que le contrôle du délai d'attente, les sessions et les limites de ré-essai peuvent vous aider à assurer le bon fonctionnement de votre application.

Timeouts

Lorsque vous faites une demande en ligne à un service externe, votre système doit attendre la réponse avant de passer à autre chose.

si votre application attend trop longtemps cette réponse, les demandes à votre service pourraient être sauvegardées, votre expérience utilisateur pourrait en souffrir ou vos jobs d'arrière-plan pourraient être suspendus.

Par défaut, les requêtes attendront indéfiniment sur la réponse, vous devriez donc presque toujours spécifier une durée de délai d'attente pour empêcher ces choses de se produire.

Pour définir le délai d'attente de la requête, utilisez le paramètre de délai d'attente. Le délai d'attente peut être un entier ou un flottant représentant le nombre de secondes d'attente d'une réponse avant le délai d'attente :

---------------------------------------------------------------------------

>>> requests.get('https://api.github.com', timeout=1)

<Response [200]>


>>> requests.get('https://api.github.com', timeout=3.05)

<Response [200]>

----------------------------------------------------------------------------

Dans la première requête, la requête sera temporisée après 1 seconde. Dans la deuxième requête, la requête sera temporisée après 3,05 secondes.

Vous pouvez également passer un tuple au timeout, le premier élément étant un timeout de connexion (le temps qu'il permet au client d'établir une connexion au serveur), et le second étant un timeout de lecture (le temps qu'il va attendre une réponse une fois que votre client aura établi une connexion) :

-----------------------------------------------------------------------------------

>>> requests.get('https://api.github.com', timeout=(2, 5))

<Response [200]>

-----------------------------------------------------------------------------------

Si la demande établit une connexion dans les 2 secondes et reçoit des données dans les 5 secondes suivant l'établissement de la connexion, la réponse sera alors renvoyée telle qu'elle était auparavant.

 Si la demande est expirée, la fonction génère une exception de délai d'attente :

---------------------------------------------------------------------------

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')


----------------------------------------------------------------------------

Le programme peut gérer  l'exception Timeout  et y répondre comme il se doit

L'objet session

Jusqu'à présent, vous traitiez des API de requêtes de haut niveau telles que get() et post(). Ces fonctions sont des abstractions de ce qui se passe lorsque vous faites vos demandes.

Ils masquent les détails de l'implémentation tels que la façon dont les connexions sont gérées afin que vous n'ayez pas à vous soucier d'eux.

Sous ces abstractions se trouve une classe appelée Session. Si vous avez besoin d'affiner votre contrôle sur la façon dont les requêtes sont faites ou d'améliorer la performance de vos requêtes, vous devrez peut-être utiliser une instance de session directement.

Les sessions sont utilisées pour persister les paramètres d'une requête à l'autre. 

Par exemple, si vous souhaitez utiliser la même authentification pour plusieurs requêtes, vous pouvez utiliser une session :



------------------------------------------------

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())


------------------------------------------------------------------

Chaque fois que vous faites une demande avec session, une fois qu'elle a été initialisée avec des informations d'authentification, les informations d'identification seront conservées.

L'optimisation primaire des performances des sessions se fait sous la forme de connexions persistantes.

Lorsque votre application établit une connexion à un serveur à l'aide d'une session, elle conserve cette connexion dans un pool de connexions.

Lorsque votre application veut se connecter à nouveau au même serveur, elle réutilisera une connexion du pool plutôt que d'en établir une nouvelle.

Nombre maximum de tentatives

Lorsqu'une demande échoue, vous pouvez vouloir que votre application réessaye la même demande. Cependant, les demandes ne le feront pas pour vous par défaut.

Pour appliquer cette fonctionnalité, vous devez implémenter un adaptateur de transport personnalisé.

Les adaptateurs de transport vous permettent de définir un ensemble de configurations par service avec lequel vous interagissez.

Par exemple, disons que vous voulez que toutes les requêtes à https://api.github.com soient réessayées trois fois avant de finalement créer une ConnectionError.

Vous devez construire un adaptateur de transport, définir son paramètre max_retries, et le monter sur une session existante :

-------------------------------------------

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)


------------------------------------------------------------------------

Lorsque vous montez le HTTPAdapter, github_adapter, à la session, session adhérera à sa configuration pour chaque requête à https://api.github.com.

Les Timeouts, les Adaptateurs de transport et les sessions sont destinés à maintenir l'efficacité de votre code et la résilience de votre application.

Conclusion

Vous avez parcouru un long chemin pour en savoir plus sur la puissante bibliothèque de requêtes de Python. Vous en êtes maintenant capable :

  • D’Effectuer des requêtes en utilisant différentes méthodes HTTP telles que GET, POST et PUT.
  • De Personnaliser vos demandes en modifiant les en-têtes, l'authentification, les chaînes d'interrogation et les corps de message.
  • D'Inspecter les données que vous envoyez au serveur et les données que le serveur vous renvoie.
  • De Travailler avec la vérification des certificats SSL
  • D'utiliser efficacement les requêtes en utilisant max_retries, timeout, Sessions, et les adaptateurs de transport.

Parce que vous avez appris à utiliser les requêtes, vous êtes en mesure d'explorer le vaste monde des services Web et de créer des applications géniales en utilisant les données fascinantes qu'elles fournissent.


Tu as bien aimé l'article ou tu as mal aux yeux :

Voici le PDF

Article écrit par :
Mikael Monjour
Data et Automatisation