2017-10-16 440 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()會給您返回任何引發的異常