pnpnpn / timeout-decorator

Timeout decorator for Python
MIT License
628 stars 94 forks source link

Unable to pass arguments to a function which uses timeout_decorator with use_signals = False #32

Closed akshay-hazari closed 7 years ago

akshay-hazari commented 7 years ago
import timeout_decorator

class abc:
    @timeout_decorator.timeout(5, use_signals=False)
    def mytest(self,arg):
        print "Start",arg
        for i in range(1,10):
            time.sleep(1)
            print "%d seconds have passed" % i

if __name__ == '__main__':
    abc().mytest("arg")

Gives an error : TypeError: mytest() takes exactly 2 arguments (1 given)

leviable commented 7 years ago

I'm not entirely sure how the _Timeout class works, but it seems like it has trouble working with class methods specifically. If you alter akshay-hazari's code to just be a function, it works fine. Some initial debugging shows that the instance reference for the abc object isn't being passed into the __call__ method:

    def __call__(self, *args, **kwargs):
        """Execute the embedded function object asynchronously.

        The function given to the constructor is transparently called and
        requires that "ready" be intermittently polled. If and when it is
        True, the "value" property may then be checked for returned data.
        """
        from pprint import pprint as pp
        import pdb
        pdb.set_trace()
        self.__limit = kwargs.pop('timeout', self.__limit)
        self.__queue = multiprocessing.Queue(1)
        args = (self.__queue, self.__function) + args
        self.__process = multiprocessing.Process(target=_target,
                                                 args=args,
                                                 kwargs=kwargs)

Using the example code:

(.venvtomp) ➜  tmp python timeoutdec.py
> /Users/levi/tmp/.venvtomp/src/timeout-decorator/timeout_decorator/timeout_decorator.py(125)__call__()
-> self.__limit = kwargs.pop('timeout', self.__limit)
(Pdb) pp(args)
('arg',)

My best guess is that the function needs to be wrapped using functools.wraps or functools.update_wrapper, but I'm not sure where that should actually happen.

dabercro commented 7 years ago

@akshay-hazari You could do the following workaround if you don't want to wait for an update:

if __name__ == '__main__':
    abc_obj = abc()
    abc_obj.mytest(abc_obj, "arg")
k2fong commented 7 years ago

This should be resolved by the merge for https://github.com/pnpnpn/timeout-decorator/pull/35. Recommend closing.