Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending threading.Timer for returning value from function gives TypeError

I tried to extend threading.Timer so I can get return values from the function. I used the solution from this thread and applied the modifications (as Timer() already takes *args and **kwargs I don't think I need to pass it through __init__ again). Code goes exactly like this:

from threading import Timer

class CustomTimer(Timer):
    def __init__(self):
        super(CustomTimer, self).__init__()
        self._return = None

    def run(self):
        super(CustomTimer, self).run()
        self._return = self._Thread__target(*self._Thread__args, **self._Thread__kwargs)

    def join(self):
        super(CustomTimer, self).join()
        return self._return

Then I get the following error running the main module:

Traceback (most recent call last):
  File "main.py", line 43, in <module>
    from storage import *
  File "/home/mei/tmwAthena/manamarket/storage.py", line 13, in <module>
    from utils import ItemDB
  File "/home/mei/tmwAthena/manamarket/utils.py", line 142, in <module>
    class CustomTimer(Timer):
TypeError: Error when calling the metaclass bases
    function() argument 1 must be code, not str

I don't understand this error since function() is quite simple, it receives *self.args and **self.kwargs and I can't see where it could be looking for a string since the initializator is pretty much the same from superclass. Note that this is occurring while importing the class, it's not even getting to be used by the code.

like image 295
Fernanda Monteiro Avatar asked Feb 20 '15 18:02

Fernanda Monteiro


People also ask

How to stop threading timer in Python?

Python timer functions start() is a function that is used to initialize a timer. To end or quit the timer, one must use a cancel() function. Importing the threading class is necessary for one to use the threading class. The calling thread can be suspended for seconds using the function time.

Does threading timer create a new Thread?

Yes, it will create new threads.

How to start a timer in Python?

start() to start a new Python timer, you first check that the timer isn't already running. Then you store the current value of perf_counter() in . _start_time .


1 Answers

The error you're getting is because Timer is not a class, it is a function/method in Python 2 threading.py:

>>> from threading import Timer
>>> type(Timer)
<type 'function'>

The concrete class is _Timer. Furthermore your code does have some problems; your init is missing arguments and the target , args, kwargs and interval are not set.

You might have luck with this CustomTimer:

from threading import _Timer

class CustomTimer(_Timer):
    def __init__(self, interval, function, args=[], kwargs={}):
        self._original_function = function
        super(CustomTimer, self).__init__(
            interval, self._do_execute, args, kwargs)

    def _do_execute(self, *a, **kw):
        self.result = self._original_function(*a, **kw)

    def join(self):
        super(CustomTimer, self).join()
        return self.result

Demo:

def add_together(a, b):
    return a + b

c = CustomTimer(1, add_together, (2, 4))
c.start()
print c.join()

prints 6 after 1 second.