2015-11-06 86 views
1

這是例如取消任務:如何取消任務執行,即使它忽略了CancelledError?

import asyncio 


async def some_func(): 
    await asyncio.sleep(2) 
    print('Haha! Task keeps running!') 
    await asyncio.sleep(2) 

async def cancel(task): 
    await asyncio.sleep(1) 
    task.cancel() 

async def main(): 
    func_task = asyncio.ensure_future(some_func()) 
    cancel_task = asyncio.ensure_future(cancel(func_task)) 
    try: 
     await func_task 
    except asyncio.CancelledError: 
     print('Task cancelled as expected') 

if __name__ == "__main__": 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(main()) 

# Task cancelled as expected 
# [Finished in 1.2s] 

它工作正常,任務被取消。如果抓到裏面some_func任務CancelledError不會被取消:

async def some_func(): 
    try: 
     await asyncio.sleep(2) 
    except: 
     pass 
    print('Haha! Task keeps running!') 
    await asyncio.sleep(2) 

# Haha! Task keeps running! 
# [Finished in 3.2s] 

它可以很容易忘記我不應該抑制異常裏面異步代碼的任何地方(或some_func可以是第三方的代碼,例如),但任務應取消。無論如何,我可以做到這一點?或者被忽略CancelledError意味着任務完全不能被取消?

回答

3

您無法取消禁止CancelledError的任務。 這是接近於無法關閉發電機,忽略GeneratorExit

這是故意的行爲。任務可能要在取消時做一些額外的工作(例如資源清理),因此捕捉CancelledError可能是個好主意,但壓制通常是編程錯誤的標誌。

Python通常允許你拍攝自己的腳,如果你有不妥協的打算這樣做。

捕獲所有異常甚至禁止通過按鍵關閉python進程,因爲它在內部被翻譯爲KeyboardInterrupt