web-dev-qa-db-fra.com

Comment puis-je abandonner une tâche dans un multitraitement.Pool après un délai d'attente?

J'essaie d'utiliser le package de multitraitement de python de cette manière:

featureClass = [[1000,k,1] for k in drange(start,end,step)] #list of arguments
for f in featureClass:
  pool .apply_async(worker, args=f,callback=collectMyResult)
pool.close()
pool.join

En ce qui concerne les processus de la piscine, je veux éviter d'attendre ceux qui mettent plus de 60 ans à renvoyer le résultat. Est-ce possible?

12
farhawa

Voici un moyen de le faire sans avoir à modifier votre fonction worker. L'idée est d'encapsuler le travailleur dans une autre fonction, qui appelle worker dans un thread en arrière-plan, puis attend un résultat pendant timeout secondes. Si le délai expire, une exception est déclenchée, qui met fin brusquement au thread worker s'exécute dans:

import multiprocessing
from multiprocessing.dummy import Pool as ThreadPool
from functools import partial

def worker(x, y, z):
    pass # Do whatever here

def collectMyResult(result):
    print("Got result {}".format(result))

def abortable_worker(func, *args, **kwargs):
    timeout = kwargs.get('timeout', None)
    p = ThreadPool(1)
    res = p.apply_async(func, args=args)
    try:
        out = res.get(timeout)  # Wait timeout seconds for func to complete.
        return out
    except multiprocessing.TimeoutError:
        print("Aborting due to timeout")
        p.terminate()
        raise

if __== "__main__":
    pool = multiprocessing.Pool()
    featureClass = [[1000,k,1] for k in drange(start,end,step)] #list of arguments
    for f in featureClass:
      abortable_func = partial(abortable_worker, worker, timeout=3)
      pool.apply_async(abortable_func, args=f,callback=collectMyResult)
    pool.close()
    pool.join()

Toute fonction qui expire avec multiprocessing.TimeoutError. Notez que cela signifie que votre rappel ne sera pas exécuté lorsqu’un délai d’expiration s’est écoulé. Si ce n'est pas acceptable, changez simplement le bloc except de abortable_worker pour renvoyer quelque chose au lieu d'appeler raise.

25
dano

nous pouvons utiliser gevent.Timeout pour définir l'heure d'exécution du travailleur. tutoriel sur gevent

from multiprocessing.dummy import Pool 
#you should install gevent.
from gevent import Timeout
from gevent import monkey
monkey.patch_all()
import time

def worker(sleep_time):
    try:

        seconds = 5  # max time the worker may run
        timeout = Timeout(seconds) 
        timeout.start()
        time.sleep(sleep_time)
        print "%s is a early bird"%sleep_time
    except:
        print "%s is late(time out)"%sleep_time

pool = Pool(4)

pool.map(worker, range(10))


output:
0 is a early bird
1 is a early bird
2 is a early bird
3 is a early bird
4 is a early bird
8 is late(time out)
5 is late(time out)
6 is late(time out)
7 is late(time out)
9 is late(time out)
1
thinkdeeper