[Python-es] Un "timeout" usando decoradores me funciona con funciones (no pun intended), pero no con métodos

Jose Caballero jcaballero.hep en gmail.com
Lun Dic 4 21:27:32 EST 2017


Hola,

Éste código funciona bien (*).
Consigo pasar un valor de "timeout' como parámetro del decorador, y la
función se aborta si se sobrepasa el límite de tiempo.

Sin embargo, si intento hacer lo mismo con un método en lugar de una
función (**), el valor de "timeout' no parece que se tenga en cuenta
en p.join().
Siempre se ejecuta el método hasta el final.

¿Qué me está faltando?

Bonus question: ¿hay alguna forma de recuperar el output de la función
"funct", si tuviese un return? Con subprocess.Popen() se puede hacer
p.communicate(), pero no veo en la documentación como hacer algo
parecido con multiprocessing.Process()

Muchas gracias por adelantado.
Jose

-------------------------------------------------------------

(*)

import multiprocessing
import time


def Timeout(timeout):
    def realdecorator(f):
        def wrapper(*k, **kw):
            p = multiprocessing.Process(target=f(*k, **kw))
            p.start()
            p.join(timeout)
            if p.is_alive():
                print('killing')
                p.terminate()
                p.join()
            else:
                print('it died already')
        return wrapper
    return realdecorator


@Timeout(3)
def funct(s):
    for i in range(100):
        print s
        time.sleep(1)


if __name__ == '__main__':
    funct('sleeping')

-------------------------------------------------------------

(**)


def Timeout(timeout):
    def realdecorator(f):
        def wrapper(*k, **kw):
            p = multiprocessing.Process(target=f(*k, **kw))
            p.start()
            p.join(timeout)
            if p.is_alive():
                print('killing')
                p.terminate()
                p.join()
            else:
                print('it died already')
        return wrapper
    return realdecorator


class MyClass(object):

    @Timeout(3)
    def funct(self, s):
        for i in range(100):
            print s
            time.sleep(1)


if __name__ == '__main__':
    o = MyClass()
    o.funct("sleeping")


Más información sobre la lista de distribución Python-es