2017-10-16 11 views
3

Comment puis-je lever l'exception dans la fonction run_long_thing() appelée avec run_in_executor? On dirait qu'il est avalé. Je n'ai pas besoin du résultat de la fonction dans le code de blocage. Il est en fait un feu et d'oublier la fonction, mais j'ai besoin de prendre les exceptions s'il y ...Comment attraper des exceptions dans un appel de méthode python run_in_executor

import asyncio 
import time 


def fire_and_forget(task, *args, **kwargs): 
    loop = asyncio.get_event_loop() 
    if callable(task): 
     #if threadpoolworker is set to None, 
     #the max_workers will default to the number of processors on the machine, multiplied by 5 
     return loop.run_in_executor(None, task, *args, **kwargs) 
    else:  
     raise TypeError('Task must be a callable.') 


async def run_long_thing(sleep): 
    print("Doing long thing... {:}".format(sleep)) 
    time.sleep(sleep) 
    print("Done doing long thing. {:}".format(sleep)) 
    raise Exception("sh*t happens") 


def do_it(): 
    print("Starting my main thing...") 
    print("Calling my long thing...") 
    for i in range(0,10,1): 
     try: 
      fire_and_forget(run_long_thing, i) 
      print(i) 
      print("Pom pi dom...") 
      time.sleep(0.1) 
      print("POOOOM Pom pi dom...") 
     except: 
      print("can i see the sh*t?") 

do_it() 

Répondre

2

d'abord, si vous appelez time.sleep vous ne serez jamais finir par courir la boucle d'événements asyncio donc aucun résultat ne sera détecté. au lieu d'appeler à time.sleepdo_it vous êtes mieux de faire quelque chose comme

asyncio.get_event_loop().run_until_complete(asyncio.sleep(0.1)) 

Maintenant, le retour de run_in_executor est un avenir. Si cela ne vous dérange pas d'écrire une définition async et en utilisant create_task sur votre asyncio boucle que vous pourriez faire quelque chose comme

async def run_long_thing(thing, *args): 
    try: await asyncio.get_event_loop().run_in_executor(None, thing, *args) 
    except: 
     #do stuff 

Mais plus en ligne avec votre code actuel, vous pouvez joindre un rappel d'exception

def callback(future): 
if future.exception(): #your long thing had an exception 
     # do something with future.exception() 

puis quand vous appelez run_in_executor:

future = asyncio.get_event_loop().run_in_executor(None, fun, *args) 
future.add_done_callback(callback) 

alors callback sera appelé à chaque fois que votre tâche exécuteur testamentaire compl etes. future.result() contiendra le résultat si ce n'est pas une exception, et future.exception() vous renverra toute exception soulevée