How to give a Timer thread a name? - python

I use a recurring python timer thread and would like to give it a name. Currently, python gives every new thread the name Thread-<number> and increments the number on every new timer start. I would like the name to remain the same. The basic Thread class supports being named, Timers, however, do not:
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *,
daemon=None)
Note the name=None attribute, which does not exist in Timer.
class threading.Timer(interval, function, args=None, kwargs=None)
Any ideas on how I can give a Timer a name? I guess I could derive my own Timer class and add name, but I don't think the python interpreter would pick it up as the thread's name...

Timers are a Thread subclass, which have names, so you can assign a custom name to one after it's created by just assigning a value to its name attribute—so it doesn't matter that the Timer constructor doesn't accept an argument allowing this.
If you do this a lot, you could write a relatively trivial utility function that automated doing this for you (or derive your own NamedTimer(Timer) subclass, which would be about the same number of lines of code):
try:
from threading import Timer
except ImportError:
from threading import _Timer as Timer # Python <3.3
def named_timer(name, interval, function, *args, **kwargs):
"""Factory function to create named Timer objects.
Named timers call a function after a specified number of seconds:
t = named_timer('Name', 30.0, function)
t.start()
t.cancel() # stop the timer's action if it's still waiting
"""
timer = Timer(interval, function, *args, **kwargs)
timer.name = name
return timer
if __name__ == '__main__':
def func():
print('func() called')
timer = named_timer('Fidgit', 3, func)
print('timer.name: {!r}'.format(timer.name)) # -> timer.name: 'Fidgit'
timer.run() # Causes "func() called" to be printed after a few seconds.

I looked for the same information and landed here. I found that one way of doing this is:
timer = Timer(interval, function)
timer.setName('AnyTimerName')

Related

Python decorator to limit rate of a function calls

I'm trying to implement a decorator that allows to limit the rate with which a function is executed.
I would like the decorator to start a timer when the function is called. If the function is called before the timer runs out, I'd like to cancel the previous call and restart the timer. When the timer ends, the function should run.
I've serched around and found this decorator. However, this decorator stops the execution of the program while the timer is running, which is something I need to avoid.
How can I achieve this?
this is rather complicated, but a simple idea is to start a timer thread and cancel it if the function is called again and start another timer thread.
now we need somewhere to store this timer ... so a dictionary should suffice, and to allow the user to choose the delay, we will just do a double wrap of functions.
from threading import Timer
from functools import wraps
import time
functions_store = {}
def main_decorator(interval):
def sub_decorator(fun):
function_id = id(fun) # since no two objects have the same id
#wraps(fun)
def new_fun(*args,**kwargs):
if function_id in functions_store:
functions_store[function_id].cancel() # cancel old timer
new_timer = Timer(interval,fun,args=args,kwargs=kwargs) # make new timer
functions_store[function_id] = new_timer # store timer to stop it later
new_timer.start()
return new_fun
return sub_decorator
#main_decorator(1) # must be called again before 1 second passes.
def func_to_run():
print("hi")
func_to_run()
time.sleep(0.5)
func_to_run()
the word "hi" will be printed after 1.5 seconds instead of 1 second because we called the function again before it fired the first time.

Access thread local object in different module - Python

I'm new to Python so please bear with my question.
Let's say my application has a module named message_printer which simply defines a print_message function to print the message. Now in my main file, I create two threads which calls print function in message_printer.
My question is: How can I set a different message per thread and access it in message_printer?
message_printer:
import threading
threadLocal = threading.local()
def print_message():
name = getattr(threadLocal, 'name', None);
print name
return
main:
import threading
import message_printer
threadLocal = threading.local()
class Executor (threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
threadLocal.name = name
def run(self):
message_printer.print_message();
A = Executor("A");
A.start();
B = Executor("B");
B.start();
This just outputs None and None while I expect A and B. I also tried accessing threadLocal object inside the print_message function directly but doesn't work.
Note that this is just an example. In my application, the exact use case is for logging. Main launches a bunch of thread which call other modules. I want to have a different logger per thread (each thread should log to its own file) and each logger needs to be configured in Main. So I'm trying to instantiate logger per thread and set in thread local storage which can then be accessed in other modules.
What am I doing wrong? I'm following this question as an example Thread local storage in Python
The problem with your code, is that you are not assigning your name to the correct local() context. Your __init__() method is run in the main thread, before you start your A and B threads by calling .start().
Your first thread creation A = Executor("A"); will create a new thread A but update the local context of the main thread. Then, when you start A by calling A.start(); you will enter A:s context, with a separate local context. Here name is not defined and you end up with None as output. The same then happens for B.
In other words, to access the thread local variables you should be running the current thread, which you are when running .start() (which will call your .run() method), but not when creating the objects (running __init__()).
To get your current code working, you could store the data in each object (using self references) and then, when each thread is running, copy the content to the thread local context:
import threading
threadLocal = threading.local()
def print_message():
name = getattr(threadLocal, 'name', None);
print name
return
class Executor (threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
# Store name in object using self reference
self.name = name
def run(self):
# Here we copy from object to local context,
# since the thread is running
threadLocal.name = self.name
print_message();
A = Executor("A")
A.start()
B = Executor("B")
B.start()
Note, though, in this situation, it is somewhat of an overkill to use the thread local context, since we already store the separate data values in the different objects. To use it directly from the objects, would require a small rewrite of print_message() though.
I think this may be helpful for your use case. Another way on how thread storage can been done across files/modules.

Killing thread in python

I defined class A which has a method like this.
def func(self):
while True:
threading.Timer(0,self.func2, ["0"]).start()
time.sleep(nseconds)
threading.Timer(0,self.func2, ["1"]).start()
time.sleep(nseconds)
If I define an instance of a this class in another script and run func method of this instance, how can I break while loop and stop these threads correctly? Do I need a ctrl-c signal handler in class A, if yes how? Note: I am also calling a system call by os.system function in func2 method of class A. Problem is when I run main script file and try to stop running of these threads, they do not stop.
There are myriads of ways to achieve what you want, one of the most straightforward ones would be using Events
from threading import Event
class Foo(object):
def __init__(self):
# the stop event is initially set to false, use .set() to set it true
self.stop_event = Event()
def func(self):
while not self.stop_event.is_set():
# your code
Meanwhile in some other thread (assuming the object your're talking about is obj):
obj.stop_event.set()
to finish the loop in the next iteration.

Why does the instance need to be recreated when restarting a thread?

Imagine the following classes:
Class Object(threading.Thread):
# some initialisation blabla
def run(self):
while True:
# do something
sleep(1)
class Checker():
def check_if_thread_is_alive(self):
o = Object()
o.start()
while True:
if not o.is_alive():
o.start()
I want to restart the thread in case it is dead. This doens't work. Because the threads can only be started once. First question. Why is this?
For as far as I know I have to recreate each instance of Object and call start() to start the thread again. In case of complex Objects this is not very practical. I've to read the current values of the old Object, create a new one and set the parameters in the new object with the old values. Second question: Can this be done in a smarter, easier way?
The reason why threading.Thread is implemented that way is to keep correspondence between a thread object and operating system's thread. In major OSs threads can not be restarted, but you may create another thread with another thread id.
If recreation is a problem, there is no need to inherit your class from threading.Thread, just pass a target parameter to Thread's constructor like this:
class MyObj(object):
def __init__(self):
self.thread = threading.Thread(target=self.run)
def run(self):
...
Then you may access thread member to control your thread execution, and recreate it as needed. No MyObj recreation is required.
See here:
http://docs.python.org/2/library/threading.html#threading.Thread.start
It must be called at most once per thread object. It arranges for the
object’s run() method to be invoked in a separate thread of control.
This method will raise a RuntimeError if called more than once on the
same thread object.
A thread isn't intended to run more than once. You might want to use a Thread Pool
I believe, that has to do with how Thread class is implemented. It wraps a real OS thread, so that restarting the thread would actually change its identity, which might be confusing.
A better way to deal with threads is actually through target functions/callables:
class Worker(object):
""" Implements the logic to be run in separate threads """
def __call__(self):
# do useful stuff and change the state
class Supervisor():
def run(self, worker):
thr = None
while True:
if not thr or not thr.is_alive():
thr = Thread(target=worker)
thr.daemon = True
thr.start()
thr.join(1) # give it some time

Multiple periodic timers

Is there any standard python module for creating multiple periodic timers.
I want to design a system which supports creating multiple periodic timers of different periodicity running in just one thread. The system should be able to cancel a specific timer at any point of time.
Thanks in advance for any input!
Check out the sched module in Python's standard library -- per se, it doesn't directly support periodic timers, only one-off "events", but the standard trick to turn a one-off event into a periodic timer applies (the callable handling the one-off event just reschedules itself for the next repetition, before moving on to doing real work).
It may be handy to define a "scheduled periodic timer" class to encapsulate the key ideas:
class spt(object):
def __init__(self, scheduler, period):
self._sched = scheduler
self._period = period
self._event = None
def start(self):
self._event = self._sched.enter(0, 0, self._action, ())
def _action(self):
self._event - self._sched.enter(self._period, 0, self._action, ())
self.act()
def act(self):
print "hi there"
def cancel(self):
self._sched.cancel(self._event)
To associate a meaningful action to a scheduled periodic timer, subclass spt and override the act method (a Template Method design pattern). You can of course choose more flexible architectures, such as having __init__ take a callable and arguments as well as a scheduler (an instance of self.scheduler) and a period (as a float in seconds, if you instantiate the scheduler in the standard way with time.time and time.sleep); optionally you might also want to set a priority there (maybe with a default value of 0) rather than using the constant 0 priority I'm using above.
If you have to stick with 1 thread - maintain a list of tasks, along with the frequency they should execute and what function should be called:
import time
def example1():
print 'Example'
class Task(object):
def __init__(self, func, delay, args=()):
self.args = args
self.function = func
self.delay = delay
self.next_run = time.time() + self.delay
def shouldRun(self):
return time.time() >= self.next_run
def run(self):
self.function(*(self.args))
self.next_run += self.delay
# self.next_run = time.time() + self.delay
tasks = [Task(example1, 1)] # Run example1 every second
while True:
for t in tasks:
if t.shouldRun():
t.run()
time.sleep(0.01)
Or you may want to have a look at stackless - which is ideally suited to what you want to do, and makes it possible to do much finer grained task-switching than the above scheduler.

Categories