2017-02-19 16 views
0

Вы можете увидеть полную фотографию here.Как отменить длительные подпроцессы, запущенные с помощью `concurrent.futures.ProcessPoolExecutor`?

упрощенная версия моего кода следующим образом:

executor = ProcessPoolExecutor(10) 
try: 
    coro = bot.loop.run_in_executor(executor, processUserInput, userInput) 
    result = await asyncio.wait_for(coro, timeout=10.0, loop=bot.loop) 
except asyncio.TimeoutError: 
    result="Operation took longer than 10 seconds. Aborted." 

К сожалению, когда операция таймаут, этот процесс все еще работает, несмотря на то, что будущий был отменен. Как мне отменить этот процесс/задачу, чтобы он фактически прекратил работу?

ответ

1

ProcessPoolExecutor использует модуль multiprocessing. Вместо того, чтобы отменить событие, которое не делает .terminate() подпроцесса, рекомендуется использовать multiprocessing.Event, чтобы позволить вашему подпроцесс, чтобы выйти правильно:

import asyncio 
import multiprocessing 
import time 
from concurrent.futures.process import ProcessPoolExecutor 


def f(done): 
    print("hi") 

    while not done.is_set(): 
     time.sleep(1) 
     print(".") 

    print("bye") 

    return 12345 


async def main(): 
    done = manager.Event() 
    fut = loop.run_in_executor(None, f, done) 
    print("waiting...") 
    try: 
     result = await asyncio.wait_for(asyncio.shield(fut), timeout=3) 
    except asyncio.TimeoutError: 
     print("timeout, exiting") 
     done.set() 
     result = await fut 
    print("got", result) 

loop = asyncio.get_event_loop() 
loop.set_default_executor(ProcessPoolExecutor()) 
manager = multiprocessing.Manager() 

loop.run_until_complete(main())