Killing thread in python - 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.

Related

Threading target function runs only one loop

I am trying to run a function in the background till some work is done in the main function and then finish the thread. I have implemented the threading logic in a separate class and the main in another file. But every time I run it the target function only seems to run once and then waits
Here is the main function
from ThreadRipper import *
thread_obj=ThreadRipper()
thread_obj.start_thread()
squish.snooze(10)
print("Main Continuing")
thread_obj.stop_thread()
And the implemented class is as follows
class ThreadRipper():
def __init__(self):
lib_path="iCOMClient.dll"
self.vx = IcomVx(lib_path)
config = ConfigParser.SafeConfigParser(allow_no_value=True)
config.readfp(open("vx_logger_config.cfg"))
self.vx.connect(config.get("icom","ip"), timeout_millis = 30000)
self.t = threading.Thread(target=self.task_to_do, args=(self.vx,))
def stop_thread(self):
self.t.do_run=False
self.t.join()
def start_thread(self):
self.t.start()
def task_to_do(self,arg):
current_thread=threading.currentThread()
while getattr(current_thread,"do_run",True):
with open("vx.txt",'a') as f:
f.write(str(arg.get_next_message()._rawmsg)+"\n")
time.sleep(1)
print("Stopping")
arg.disconnect()
When I run this I get the vx file created but with only one entry, I expect it to be written to continuously till the while loop exits. I am quite new at threading and may have understood it incorrectly. Please advise
Thank you
The reason is probably because
print("Stopping")
arg.disconnect()
are both inside the while loop. After disconnecting, arg doesn't seem to produce any more messages.
(Unless, of course, your code in the question is not what you really have, but in this case, you surely would have edited your question so it matches.)

How to give a Timer thread a name?

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')

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

How to call same process multiple times in a program

I am using python 2.7 multiprocessing module.I want to start a process and then terminate it and then start it again with new arguments.
p = Process(target=realwork, args=(up, down, middle, num))
def fun1():
p.start()
def fun2():
p.terminate()
And in the course of the program flow (through loops and events) I call the functions in this order:
fun1()
fun2()
fun1()
fun2()
If I try that i get an error saying I cannot call same process multiple times. Is there a workaround?
So - ypu probably had read somewhere that "using global variables is not a good pratice" - and this is why. Your "p" variable only holds one "Process" instance, and it can only be started (and terminated) once.
If you refactor your code so that "fun1" and "fun2" take the process upon which they act as a parameter, or maybe in an O.O. way, in which fun1 and fun2 are methods and the Process is an instance variable, you would not have any of these problems.
In this case, O.O. is quick to see and straightforward to use:
class MyClass(object):
def __init__(self):
self.p = Process(target=realwork,args=(up,down,middle,num))
def fun1(self):
self.p.start()
def fun2(self):
self.p.terminate()
And then, wherever you need a pair of calls to "fun1" and "fun2", you do:
action = Myclass()
action.fun1()
action.fun2()
instead. This would work even inside a for loop, or whatever.
*edit - I just saw ou are using this as answer to a button press in a Tkinter
program, so, you have to record the Process instance somewhere between button clicks.
Without having your code to refactor, and supposing you intend to persist
on your global variable approach, you can simply create the Process instance inside
"fun1" - this would work:
def fun1():
global p
p = Process(target=realwork,args=(up,down,middle,num))
p.start()
def fun2():
p.terminate()
Once you terminate a process, it's dead. You might be able to restructure the process to be able to communicate with it using pipes, for instance. That may be difficult to get right if the child process is not well-behaved. Otherwise, you can just create a new instance of Process for each set of arguments.

When a QThread has an event queue, is it safe to terminate the thread with exit()?

I'm using QThread to do some periodic background work, the source code looks something like this
class Worker(QObject):
""" Separate QObject that does the work with affinity of
'DoStuffOnceASecond'"""
def __init__(self):
super(QWorker, self).__init__()
def doWork(self):
#... do work, post signal to consumer
class DoStuffOnceASecond(QThread):
def __init__(self):
super(DoStuffOnceASecond, self).__init__()
def run(self):
""" Setup "pullFiles" to be called once a second"""
self.timer= QTimer()
self.worker = Worker()
self.timer.setSingleShot(False)
self.timer.timeout.connect(self.worker.doWork)
self.timer.start(1000)
self.exec_()
I'm looking for the best way to terminate such a thread. One option would be to post a signal from the main thread to this thread, creating a slot in this thread. Since these slots execute as part of the event loop, they would get safely picked up. But then I'd be self terminating... and I'm not sure if that would work very well.
Or I'm wondering, since the thread should be conscious that its running an event loop, if its safe just to call exit() on this thread? The documentation seems to indicate this is ok:
After calling this function, the thread leaves the event loop and returns from the call to QEventLoop::exec(). The QEventLoop::exec() function returns returnCode.
I think "leaves the event loop" means it will allow the current event to finish processing. Or does the QThread instantly terminate?
The code here is python (pyside 1.10, python 2.7) but this could easily apply to any QT code using QThread.
You don't need to declare any extra slots, if you don't mind that your return code will be 0. Then you can use already defined quit() slot which just calls exit(0) on your thread. About your fear to "self-terminate" - you are not terminating the thread, just quitting its event loop. And you can start it anytime by calling exec() again. You are still very nice to your thread so everything should "work very well". Instant termination is possible by QThread::terminate but is meant as last desperate mean to kill off the thread when the above method has failed.

Categories