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')
Related
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)
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
I want to run a function every few seconds in Python. The function execution takes some time, and I want to include that in the waiting time as well.
I don't want to do this, because it is not strictly executed every 2 seconds and will break the periodicity (my_function also takes time to execute.)
while True:
time.sleep(2)
my_function()
I don't want to do this neither, because it uses too much CPU on the while loop of Thread-2.
# Thread-1
While True:
time.sleep(2)
event.set()
# Thread-2
While True:
if event.is_set():
my_function()
else:
pass
Can anyone please help me?
You can consider ischedule. It takes care of the function execution time right out the box, and doesn't waste CPU time for busy waiting. You can use:
from ischedule import schedule, run_loop
schedule(my_function, interval=2)
run_loop()
I believe the schedule module is your friend
I found this code works pretty well, if I understood your question correctly.
Code broken down:
runs func1
runs func2
waits 2s
does something else after that
waits 1s
does it all again
import threading
import time
def func1():
print("function 1 has been called")
def func2():
print("function 2 has been called")
def loop():
print("loop print 1")
thread = threading.Thread(target=func1, name="thread")
thread.start()
while thread.is_alive():
continue
if not thread.is_alive():
thread2 = threading.Thread(target=func2, name="thread2")
thread2.start()
while thread2.is_alive():
continue
time.sleep(2)
while True:
loop()
print("Some other thing")
time.sleep(1)
I am trying to create a timer working thread, which can exit at any time.
python has a build in timer, whose callback function is called only ONCE?!
I have no idea why it is called timer.
Then I have to put a sleep in the working thread, which is a bad idea. timerThread.cancel() cannot shutdown the working thread. If I use event to exit the working thread, the working thread can exit only after wake up.
I am expecting a timer working thread, which can exit at any time. and I don't want the working thread blocked.
Are there some ways to realize it?
def Show():
while 1:
time.sleep(10)
print("Nice!")
if __name__ == '__main__':
timerThread = threading.Timer(1,Show)
timerThread.start()
while 1:
input = str(sys.stdin.readline())
if input == 'EXIT\n':
timerThread.cancel()
break;
To your point, the Timer object [1] in python runs just once and after some period of time executes a function. That function, though, can start a new Timer object. An example of this implementation is below.
timerThread = None
def timesUp():
global timerThread
print('Nice!')
timerThread = Timer(10, timesUp)
timerThread.start()
def main():
global timerThread
timerThread = Timer(10, timesUp)
timerThread.start()
while 1:
input = str(sys.stdin.readline())
if input == 'EXIT\n':
timerThread.cancel()
break;
Overall, due to GIL [2] issues in python, you'll have issues with threading properly, as only 1 thread has access to the interpreter at a time. This is why a lot of frameworks in python are single threaded, asynchronous frameworks (e.g. gevent [3], tornado [4]). Instead of using threads they listen on an IOLoop (eventlets, epoll) and cooperatively yield operation flow to the other waiting coroutines.
[1] - https://docs.python.org/2/library/threading.html#timer-objects
[2] - https://wiki.python.org/moin/GlobalInterpreterLock
[3] - http://www.gevent.org/
[4] - http://www.tornadoweb.org/en/stable/
You can use this class to solve your problem.
import time
from threading import Thread
class Timer(Thread):
def __init__(self, seconds, callback, *args, **kwargs):
Thread.__init__(self)
assert callable(callback)
self.__callback = callback
self.__seconds = seconds
self.__args = args
self.__kwargs = kwargs
self.running = False
def run(self):
self.running = True
while self.running:
Thread(target=self.__callback, args=self.__args, kwargs=self.__kwargs).start()
time.sleep(self.__seconds)
def stop(self):
self.running = False
To call this function use
def Test(spam,eggs=10):
print spam, eggs
timerFunction = Timer(1,Test,10,eggs=99) # The number 1 is the time in seconds
timerFunction.start()
To stops the execution use:
timerFunction.stop()
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.