2017-10-16 214 views
3

如何在run_in_executor调用的run_long_thing()函数中引发异常? 它看起来像被吞咽。我不需要阻塞代码中的函数结果。它基本上是一个射后不理功能,但我仍然需要捕获异常,如果有任何...如何在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() 

回答

2

首先,如果你打电话time.sleep你永远不会结束运行asyncio事件循环所以没有检测到结果。而不是调用do_ittime.sleep你最好不要做这样

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

东西现在,从run_in_executor返回的是一个未来。如果你不介意写一个异步的def使用create_taskasyncio循环,你可以做类似

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

但更与您当前的代码,你可以将一个异常回调

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

那么当你调用run_in_executor:

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

然后callback将被调用时,您的执行人任务并发症ETES。 future.result()将包含结果,如果它不是例外,并且future.exception()会给您返回任何引发的异常