Blog ENI : Toute la veille numérique !
🎁 Jusqu'au 25/12 : 1 commande de contenus en ligne
= 1 chance de gagner un cadeau*. Cliquez ici
🎁 Jusqu'au 31/12, recevez notre
offre d'abonnement à la Bibliothèque Numérique. Cliquez ici
  1. Livres et vidéos
  2. Python 3
  3. Programmation asynchrone : alternatives
Extrait - Python 3 Traitement de données et techniques de programmation (2e édition)
Extraits du livre
Python 3 Traitement de données et techniques de programmation (2e édition) Revenir à la page d'achat du livre

Programmation asynchrone : alternatives

Gevent

1. Introduction

La bibliothèque Gevent permet de créer en Python des coroutines pour gérer efficacement des problématiques réseau. Elle est basée sur l’utilisation de greenlet et une boucle événementielle performante (libev ou libuv). L’installation se fait ainsi :

$ pip install gevent 

La bibliothèque contient donc un objet socket qui travaille de manière concurrente et quelques fonctions utiles, comme le montre cet exemple adapté de la documentation officielle :

>>> from gevent import socket, spawn, joinall 
>>> urls = ["eni.fr", "www.inspyration.fr", "www.python.org"]  
>>> jobs = [spawn(socket.gethostbyname, url) for url in urls] 
>>> joinall(jobs, timeout=10) 
>>> [job.value for job in jobs] 
['185.42.28.200', '213.246.53.26', '151.101.40.223'] 

Dans cet exemple, on va demander l’IP associée à un nom d’hôte et on va créer plusieurs tâches pour chaque hôte, pour les mettre en concurrence.

La fonction joinall permet d’attendre que toutes les tâches soient terminées. La dernière ligne permet de récupérer le résultat de chaque tâche.

2. DNS

Gevent inclut les outils nécessaires pour la résolution de nom de domaine, comme l’exemple précédent en est une illustration. Il s’agit d’une réécriture iso-fonctionnelle partielle des fonctionnalités présentes dans le module python socket. Vous pourrez donc consulter la documentation officielle pour savoir comment ces fonctions doivent être utilisées et...

Twisted

1. Introduction

Twisted est un outil permettant de créer un serveur internet et non pas seulement un serveur web. En d’autres mots, il ne gère pas que le protocole HTTP, mais il peut faire du WebDav, du FTP ou implémenter vos propres protocoles.

Pour l’installer :

$ pip install twisted 

L’objet central est un réacteur et ce dernier va faire tourner des protocoles, lesquels sont des descriptions des données attendues et des réponses à fournir. Ces protocoles sont construits au-dessus de transports, tels que le transport TCP ou UDP.

2. Client/serveur TCP

Voici un exemple de serveur TCP Basique : il renvoie tel un écho la donnée qu’il reçoit. On va commencer par importer ce dont nous aurons besoin :

from twisted.internet import reactor 
from twisted.internet.protocol import Protocol, ServerFactory 

Voici un exemple simple de protocole permettant de renvoyer la donnée reçue :

class Echo(Protocol): 
    def dataReceived(self, data): 
        "As soon as any data is received, echo it back." 
        self.transport.write(data) 

Il suffit alors de connaître les différentes fonctions à surcharger pour créer son propre protocole et lui faire faire ce que l’on souhaite.

Pour faire tourner ce protocole, il faut monter le réacteur :

def main(): 
    """This runs the protocol on port 8000""" 
    factory = ServerFactory() 
    factory.protocol = Echo 
    reactor.listenTCP(8000,factory) 
    reactor.run() 

Ce code devrait vous sembler assez familier si vous avez déjà lu les chapitres Programmation réseau et Programmation web.

Il faut ensuite l’exécuter :

if __name__ == '__main__': 
    main() 

Pour la partie cliente, on écrit également un protocole :

class EchoClient(protocol.Protocol): 
 
    def connectionMade(self): 
        self.transport.write(b"hello, world!") 
 
    def dataReceived(self, data): ...

Trollius

Comme vous le savez, asyncio est disponible seulement pour Python 3.4 ou supérieur. Une alternative existe cependant pour Python 2.7 dont la branche est toujours active et le restera encore quelques années.

Tout comme asyncio, trollius offre une boucle événementielle ainsi que des transports et protocoles parmi lesquels on peut trouver TCP, UDP ou SSL comme nous vous l’avons présenté dans le chapitre Programmation asynchrone : avancée. Cependant, attention, ces protocoles sont basés sur ceux de twisted plus que sur ceux d’asyncio. C’est une des raisons pour laquelle nous avons introduit twisted juste au-dessus.

Ce module vous permettra aussi, plus basiquement, de créer des coroutines et des tâches et de les synchroniser.

Voici un exemple de protocole UDP (très ressemblant à ce que vous avez pu voir précédemment) :

class ServerUdpEchoProtocol: 
 
    def connection_made(self, transport): 
        print('{transport} started'.format(transport=transport)) 
        self.transport = transport 
 
    def datagram_received(self, data, addr): 
        print('Data {data} received from {addr}'.format(data=data...

HTTP asynchrone avec aiohttp

1. Côté serveur

Nous vous avons déjà présenté bottlepy et évoqué l’alternative flask. Il s’agit de microframeworks web permettant de répondre à des besoins simples.

Il existe une alternative qui, syntaxiquement, est extrêmement proche et qui présente l’avantage d’utiliser la programmation asynchrone.

Voici l’exemple d’introduction de aiohttp :

from aiohttp.web import  RouteTableDef, Response , Application,  run_app 
 
routes = RouteTableDef() 
 
@routes.get('/') 
async def hello(request): 
    return Response(text="Hello World!") 
 
app = Application() 
app.add_routes(routes) 
run_app(app) 

À comparer à un exemple similaire avec bottlepy :

from bottle import route, run, template 
 
@route('/') 
def index(): 
    return "Hello World!"  
run(host="localhost", port=8080) 

ou Flask :

from flask import Flask 
app = Flask("test App") 
 
@app.route("/") 
def hello(): 
    return "Hello World!" 

Avec aiohttp, les méthodes peuvent s’écrire en utilisant la programmation asynchrone :

from aiohttp.web import json_response 
 
async def test(self...