2017-06-10 2 views
0

J'essaie de comprendre comment remettre en file d'attente certaines requêtes DNS asynchrones qui ont expiré (j'utilise les modules uvloop et aiodns).Redéfinissez les futures après exception avec asyncio

Voici le code que je mis en place la boucle avec:

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) 
loop = asyncio.get_event_loop() 
resolver = aiodns.DNSResolver(loop=loop) 
sem = asyncio.Semaphore(MAX_COUNT) 

Cette fonction effectue la recherche:

async def lookup(name): 
    with (await sem): 
     response = await resolver.query(name, 'A') 
     return response 

Je lis dans un fichier contenant les noms pour rechercher et définir des tâches, y compris un rappel pour gérer les résultats:

for n in names: 
    host = '{}.{}'.format(n, domain) 
    task = asyncio.ensure_future(lookup(host)) 
    tasks.append(task) 
    task.add_done_callback(functools.partial(got_result, host)) 

Et démarrez la file d'attente de recherche.

print("Looking up {} subdomains...".format(len(names))) 
loop.run_until_complete(asyncio.wait(tasks)) 
loop.close() 

Dans le rappel got_result je puis tester future.exception() et traiter s'il y a un, et sinon imprimer le résultat à l'écran. Certaines des exceptions que je vais bien (c'est-à-dire le nom de domaine non trouvé), mais d'autres comme un délai d'attente, je veux remettre en file d'attente l'élément. Y a-t-il un moyen facile d'ajouter le futur à la boucle pour un autre essai ou ai-je besoin de mettre en place une fonction séparée pour cela et rajouter une tâche manuellement?

Merci pour votre aide.

Répondre

2

Question: ... mais d'autres comme un temps mort, je veux à nouveau la file d'attente l'élément.

requeue la tâche pourrait conduire à une Deadlock.
Au lieu de requeue la tâche, maintenez la tâche, par exemple:

async def lookup(name): 
    with (await sem): 
     retries = 0 
     while retries <= 5: 
      try: 
       response = await resolver.query(name, 'A') 
       break 
      except TimeoutError: 
       retries += 1 
       yield from asyncio.sleep(1) 

     return response    
+0

Merci beaucoup, je ne pensais pas à traiter avec de cette manière. Je vais vous donner un coup de feu. – Blark