Can Python Timer be canceled by checking if it exists? - python

I want to check if the timer exists and simply stop it by running the following code a second time, but instead it waits for the timer to stop
and runs again.
import time
import threading
def run():
print("foobar")
t = threading.Timer(3, run)
def stop_t():
time.sleep(1)
t.cancel()
print("canceled")
if t.is_alive():
t.cancel()
else:
t.start()

The problem is that if you run this code again, you will redefine the t variable to a new timer that has not started yet, you can try something like this:
import time
import threading
def run():
print("foobar")
def toggle_timer(t):
if t.is_alive():
print('timer is alive, killing it')
t.cancel()
else:
t.start()
print('timer is dead, starting it')
t = threading.Timer(3, run)
toggle_timer(t)
toggle_timer(t)
Output:
timer is dead, starting it
timer is alive, killing it

Related

How to terminate a loop early in in a thread?

I have a loop which makes a get request to a webservice to fetch data and do some stuff, but I want to 'manually' terminate the thread/event, which I achieved with the following example:
from threading import Event
exit = Event()
if external_condition():
exit.set()
for _ in range(mins):
fetch_data_and_do_stuff()
exit.wait(10) #wait 10 seconds
With that, the only thing that terminates it's the sleep time between loops. How can I also kill the loop so it doesn't keep running until it gets to the last iteration?
nvm i've solved it like this
from threading import Event
exit = Event()
if external_condition():
exit.set()
for _ in range(mins):
fetch_data_and_do_stuff()
if exit.wait(10):
break
the condition returns true when killed and also sleeps the 10 seconds, so it works
you have 2 options ,
kill the thread or process entirely
or making the loop's boolean false. going that way
you could use a global variable in this way: [Python 3.7] , run it to see
from threading import Thread
from time import sleep
global glob
glob=True
def threaded_function():
while glob:
print("\n [Thread] this thread is running until main function halts this")
sleep(0.8)
if __name__ == "__main__":
thread = Thread(target = threaded_function, args = ())
thread.start()
for i in range(4,0,-1):
print("\n [Main] thread will be terminated in "+str(i)+" seconds")
sleep(1)
glob=False
while True:
print("[Main] program is over")
sleep(1)

Is sys.exit(0) a valid way to exit/kill a thread in python?

I'm writing a timer in python. When the timer reaches 0, I want the thread I made to automatically exit.
class Rollgame:
timer = 0
def timerf(self, timer):
self.timer = timer
while self.timer > 0:
time.sleep(0.1)
self.timer -= 0.1
sys.exit(0)
Is this a valid way to exit a thread? It seems to be working in the context of the program im building, however I'm not sure if it's a good way to do it.
If I ever choose to implement this in something like a flask/django app, will this still be valid?
Sorry if the question seems stupid or too simple, I've never worked with threading in python before.
In general, killing threads abruptly is considered a bad programming practice. Killing a thread abruptly might leave a critical resource that must be closed properly, open. But you might want to kill a thread once some specific time period has passed or some interrupt has been generated. There are the various methods by which you can kill a thread in python.
Set/Reset stop flag :
In order to kill a threads, we can declare a stop flag and this flag will be check occasionally by the thread. For Example:
# Python program showing
# how to kill threads
# using set/reset stop
# flag
import threading
import time
def run():
while True:
print('thread running')
global stop_threads
if stop_threads:
break
stop_threads = False
t1 = threading.Thread(target = run)
t1.start()
time.sleep(1)
stop_threads = True
t1.join()
print('thread killed')
In the above code, as soon as the global variable stop_threads is set, the target function run() ends and the thread t1 can be killed by using t1.join(). But one may refrain from using global variable due to certain reasons. For those situations, function objects can be passed to provide a similar functionality as shown below:
# Python program killing
# threads using stop
# flag
import threading
import time
def run(stop):
while True:
print('thread running')
if stop():
break
def main():
stop_threads = False
t1 = threading.Thread(target = run, args =(lambda : stop_threads, ))
t1.start()
time.sleep(1)
stop_threads = True
t1.join()
print('thread killed')
main()
Using traces to kill threads :
This methods works by installing traces in each thread. Each trace terminates itself on the detection of some stimulus or flag, thus instantly killing the associated thread. For Example:
# Python program using
# traces to kill threads
import sys
import trace
import threading
import time
class thread_with_trace(threading.Thread):
def __init__(self, *args, **keywords):
threading.Thread.__init__(self, *args, **keywords)
self.killed = False
def start(self):
self.__run_backup = self.run
self.run = self.__run
threading.Thread.start(self)
def __run(self):
sys.settrace(self.globaltrace)
self.__run_backup()
self.run = self.__run_backup
def globaltrace(self, frame, event, arg):
if event == 'call':
return self.localtrace
else:
return None
def localtrace(self, frame, event, arg):
if self.killed:
if event == 'line':
raise SystemExit()
return self.localtrace
def kill(self):
self.killed = True
def func():
while True:
print('thread running')
t1 = thread_with_trace(target = func)
t1.start()
time.sleep(2)
t1.kill()
t1.join()
if not t1.isAlive():
print('thread killed')
In this code, start() is slightly modified to set the system trace function using settrace(). The local trace function is defined such that, whenever the kill flag (killed) of the respective thread is set, a SystemExit exception is raised upon the excution of the next line of code, which end the execution of the target function func. Now the thread can be killed with join().
Finally, Using the multiprocessing module to kill threads :
The multiprocessing module of Python allows you to spawn processes in the similar way you spawn threads using the threading module. The interface of the multithreading module is similar to that of the threading module. For Example, in a given code we created three threads(processes) which count from 1 to 9. Now, suppose we wanted to terminate all of the threads. You could use multiprocessing to do that.
# Python program killing
# a thread using multiprocessing
# module
import multiprocessing
import time
def func(number):
for i in range(1, 10):
time.sleep(0.01)
print('Processing ' + str(number) + ': prints ' + str(number*i))
# list of all processes, so that they can be killed afterwards
all_processes = []
for i in range(0, 3):
process = multiprocessing.Process(target=func, args=(i,))
process.start()
all_processes.append(process)
# kill all processes after 0.03s
time.sleep(0.03)
for process in all_processes:
process.terminate()
To sum it up, there are many ways to terminate threads, but I peronally wouldn't use sys.exit().

Alternative for threading.timer python

I am trying to implement a timer for calling the function for printing the queue after specific time .I am also able to cancel the timer if the queue gets filled before that specified time and print the queue.But after that my timer object behaves abruptly causing timers to overlap for example if the queue gets filled in 2 sec then it prints the queue in 2,8,2,8... time interval instead of 2,10 time interval
connection = pika.BlockingConnection(pika.ConnectionParameters(host='127.0.0.1'))
channel = connection.channel()
channel.queue_declare(queue='final', durable=True)
global msg_queue
global t
msg_queue=queue.Queue(maxsize=6)
def empty_queue():
print(time.time())
l=[]
i=int(msg_queue.qsize())
while i!=0:
l.append(msg_queue.get())
i-=1
t=threading.Timer(10,empty_queue)
print(l)
t.start()
t=threading.Timer(10,empty_queue)
print(time.time())
t.start()
while True:
if int(msg_queue.qsize())<6:
consume_generator = channel.consume(queue='final', no_ack=True)
result=next(consume_generator)
msg_queue.put(json.loads(result[2].decode("utf-8")))
else:
print("more",time.time())
t.cancel()
empty_queue()
I have solved the issue by cancelling the timer to prevent its own duplicacy
def empty_queue():
global t
print(time.time())
l=[]
i=int(msg_queue.qsize())
while i!=0:
l.append(msg_queue.get())
i-=1
if t.isAlive():
t.cancel()
t=threading.Timer(10,empty_queue)
print(l)
t.start()
You could nest a if statement inside the timer that says if queue is full then disable this if statement then let the timer continue until its done without affecting the queue. I don't think it will cause conflict with your program because the timer is probably a closure.

Python threading.Timer not waiting before executing function

I have thrown together a quick threading test:
import threading
def test():
print "it don't work"
while True:
threading.Timer(1, test).start()
It runs test, but it doesn't wait. What's wrong?
In each loop iteration, you start a new thread. Therefore you will reach the limit of allowed thread and you will get an exception : can't start new thread.
while True:
threading.Timer(1, test).start()
You can add global flag and wait until the function is executed - You should use time.sleep to avoid busy waiting.
a = False
def test():
global a
print("hallo")
a = True
threading.Timer(10, test).start()
while not a:
time.sleep(1)
print('done')

python thread weird behavior

I have a timer function which I am calling it in another function like this
import time
import threading
def f():
while(True):
print "hello"
time.sleep(5)
def execute():
t = threading.Timer(5,f)
t.start()
command = ''
while command != 'exit':
command = raw_input()
if command == 'exit':
t.cancel()
Even if after entering "exit" command, the function is printing "hello"
I am not able to figure out Whats wrong with the code
class threading.Timer - cancel() - Doc-Link
Stop the timer, and cancel the execution of the timer’s action. This will only work if the timer is still in its waiting stage.
A very simple Version of what you are trying to accomplish could look like this.
import threading
_f_got_killed = threading.Event()
def f():
while(True):
print "hello"
_f_got_killed.wait(5)
if _f_got_killed.is_set():
break
def execute():
t = threading.Timer(5,f)
t.start()
command = ''
while command != 'exit':
command = raw_input()
if command == 'exit':
_f_got_killed.set()
t.cancel()
execute()
For forcefully killing a thread look at this:
Is there any way to kill a Thread in Python?
You are using cancel wrong. In http://docs.python.org/2/library/threading.html, it states: "Timers are started, as with threads, by calling their start() method. The timer can be stopped (before its action has begun) by calling the cancel() method. The interval the timer will wait before executing its action may not be exactly the same as the interval specified by the user."
In your code, if you try to use cancel after the timed thread has already begun its execution (it will in 5 seconds), cancel accomplishes nothing. The thread will remain in the while loop in f forever until you give it some sort of forced interrupt. So typing "exit" in the first 5 seconds after you run execute works. It will successfully stop the timer before the thread even begins. But after your timer stops and your thread starts executing the code in f, there will be no way to stop it through cancel.

Categories

Resources