How to cancel a setInterval in python? - python

I am using this code to call a function doSomething every 3 seconds. but I want that when numeroPeticiones== 3, stop doing it. I have looked for many examples, but none works. In my case, my function continues to be executed eternally, even though the condition of numeroPeticiones== 3 is fulfilled. how can I solve that?
import threading
from threading import Timer
numeroPeticiones=0
def doSomething():
global numeroPeticiones
numeroPeticiones=numeroPeticiones+1
print ("hello, world",numeroPeticiones)
if numeroPeticiones == 3:
print("cancel")
t.cancel()
def set_interval(func, sec):
def func_wrapper():
set_interval(func, sec)
func()
t = threading.Timer(sec, func_wrapper)
t.start()
return t

You can do the following, if num is equal to the 3, it wont start the timer
from threading import Timer
num = 0
def hello():
global num
num += 1
print("hello, world")
if (num < 3):
Timer(3, hello).start()
Timer(3, hello).start()

Related

How can I increment a variable inside a function without using global variable please?

I need a way to print a timer every second and execute an action every 10 seconds.
The output of the program should be like below.
Timer is 1
Timer is 2
Timer is 3
Timer is 4
Timer is 5
Timer is 6
Timer is 7
Timer is 8
Timer is 9
Timer is 10
Action is executed
Timer is 1
Timer is 2
Timer is 3
Timer is 4
Timer is 5
Timer is 6
Timer is 7
Timer is 8
Timer is 9
Timer is 10
Action is executed
Timer is 1
Timer is 2
Timer is 3
.
.
.
The program should use threading. It should not be an infinite while loop.
I could have done it with below code but it uses a global variable. How can I do it without using a global variable and with a small amount of code like below.
import threading
import time
global MytTimer
MytTimer=0
def foo():
global MytTimer
MytTimer=MytTimer+1
print("Timer is " + str(MytTimer))
threading.Timer(1, foo).start()
if MytTimer >= 10:
MytTimer=0
print("Action is executed")
foo()
I did it by creating a class.
import threading
import time
class count():
def __init__(self, MytTimer):
self.MytTimer = MytTimer
self._run()
def _run(self):
threading.Timer(1, self._run).start()
self.MytTimer += 1
print("Timer is " + str(self.MytTimer))
if self.MytTimer >= 10:
self.MytTimer=0
print("Action is executed")
a=count(MytTimer = 0)
You could create a ticker thread that delivers values 1-10 to a queue, and then a consumer that executes an action whenever the value read from the queue is 10:
import threading
import time
import queue
def foo():
q = queue.Queue()
def ticker():
while True:
for i in range(1,11):
print(f'Timer is {i}')
q.put(i)
time.sleep(1)
t_ticker = threading.Thread(target=ticker)
t_ticker.start()
while True:
i = q.get()
if i == 10:
print("Action is executed")
foo()

Python Thread counter

I'm trying to make thread counter but I'm stuck. I've got the code below:
import threading
def Hello():
global t
print("Hello!")
t = threading.Timer(1, Hello)
t.start()
Hello()
How can I make the loop stop say after 5 'Hellos'?
Not sure what you're trying to accomplish but this code will work
import threading
count = 0
def hello():
global count
print("Hello!")
count += 1
if count < 5:
t = threading.Timer(1, function=hello,)
t.start()
hello()

How to call a function only once every X time in an infinite loop in python?

I have a Python program with many functions that I call inside a while loop.
I need my while loop to call all the functions the first time it does the loop, but then I would want to call one of those functions only once every two minutes.
Here is a code example:
def dostuff():
print('I\'m doing stuff!')
def dosthings():
print('I\'m doing things!')
def dosomething():
print('I\'m doing something!')
if __name__ == '__main__':
while True:
dostuff()
print('I did stuff')
dosthings()
print('I did things') #this should run once every X seconds, not on all loops
dosomething()
print('I did something')
How can I achieve this result? Have I to use multithreading/multiprocessing?
Here's a quick-and-dirty single threaded demo, using time.perf_counter(), you can alternatively use time.process_time() if you don't want to include time spent in sleep:
import time
# Changed the quoting to be cleaner.
def dostuff():
print("I'm doing stuff!")
def dosthings():
print("I'm doing things!")
def dosomething():
print("I'm doing something!")
if __name__ == '__main__':
x = 5
clock = -x # So that (time.perf_counter() >= clock + x) on the first round
while True:
dostuff()
print('I did stuff')
if time.perf_counter() >= clock + x:
# Runs once every `x` seconds.
dosthings()
print('I did things')
clock = time.perf_counter()
dosomething()
print('I did something')
time.sleep(1) # Just to see the execution clearly.
See it live

Problem with cancelling timer within a function (python)

I have a function constantly running in a loop checking if it should start or cancel a timer that's defined in the function's scope. Timer needs to be defined within the function as the callback is also defined in the function. I'm able to start the timer fine, but when it tries to cancel, I get an error 'local variable 'timer' referenced before assignment'.
I've tried defining the timer and its callback in the global scope (which is undesirable), and I get another error 'threads can only be started once'.
import threading
import random
def start():
trigger = random.randint(0,1)
def do_something():
print(trigger)
if trigger == 0:
timer = threading.Timer(2,do_something)
timer.start()
else:
timer.cancel() #: if trigger is 1, I want to cancel the timer
threading.Timer(1,start).start() #: start() is in a loop and is constantly checking trigger's value
start()
I want the same timer to be started or cancelled according to trigger's value. timer and its callback should be defined within the function.
This program shows how a random number can be used to start or stop a timer.
If the random number selects 0 enough times in a row, the timer will be started and be allowed to continue timing until time runs out and it calls its target.
If ever the random number selects 1, the timer is cancelled and the target is not called:
import threading
import random
import time
class Timing:
def __init__(self):
self.timer = None # No timer at first
self.something = None # Nothing to print at first
self.restart()
def restart(self):
self.run = threading.Timer(1.1, self.start)
self.run.start()
def cancel(self):
if self.run is not None:
self.run.cancel()
self.run = None
def start(self):
trigger = random.randint(0, 1)
self.do_start(trigger)
def do_start(self, trigger):
print('start', trigger)
if trigger == 0:
if self.timer is None:
self.something = trigger
self.timer = threading.Timer(2, self.do_something)
self.timer.start()
else:
if self.timer is not None:
self.timer.cancel()
self.timer = None
self.something=None
self.restart()
def do_something(self):
print(self.something)
t = Timing()
print('sleeping...')
time.sleep(20)
t.cancel()
t.do_start(1)
t.cancel()
print('Done')
Sample output (ymmv because its random)
sleeping...
start 1
start 0
start 1
start 0
start 0
0
start 1
start 0
start 1
start 1
start 1
start 1
start 1
start 0
start 1
start 0
start 0
0
start 1
start 0
start 1
Done
I've learnt from #quamrana and #smci and came up with this
import threading
import random
class Timer():
pass
t = Timer()
def start():
trigger = random.randint(0,1)
def do_something():
print(trigger)
if trigger == 0:
t.timer = threading.Timer(1,do_something)
t.timer.start()
else:
if hasattr(t,'timer'):
t.timer.cancel()
threading.Timer(1,start).start()
start()
This seems to solve the issue while keeping the code compact.

Cancel timer in Python

I am working on timer class in python and wrote a simple test code for the same. My purpose is to print the "hello world" message 10 times and then cancel the timer once the iterations are done. The problem is I am unable to cancel the timer and code seems to print "hello world" infinitely.
Below is my code:
from threading import Timer
class myclass():
iteration_count = 0
heartbeat = 1
def printMsg(self):
print "hello world!"
def start_job(self):
self.printMsg()
self.iteration_count = self.iteration_count + 1
if self.iteration_count == 10:
Timer(self.heartbeat, self.start_job, ()).cancel()
Timer(self.heartbeat, self.start_job, ()).start()
m = myclass()
m.start_job()
I am using Python 2.7
Any help would be highly appreciated
Your problem is you've made another Timer() in if condition and .cancel() it. The following code solves your problem:
from threading import Timer
class MyClass(object):
def __init__(self):
self.iteration_count = 0
self.heartbeat = 1
#staticmethod
def print_msg():
print "hello world!"
def start_job(self):
self.print_msg()
self.iteration_count += 1
timer = Timer(
interval=self.heartbeat,
function=self.start_job,
)
timer.start()
if self.iteration_count >= 10:
timer.cancel()
MyClass().start_job()
Seems like you start your timer again right after you cancelled it.
If you change your code to return from start_job() when your end-condition is reached it should work.
if self.iteration_count == 10:
Timer(self.heartbeat, self.start_job, ()).cancel()
return
Actually you don't even have to cancel the timer this way, you just don't start a new one, if the condition is reached.
cancelmethod is used to stop the created timer before its action has begun, so just return will be ok.
if self.iteration_count == 10:
return
See Timer Objects
The timer can be stopped (before its action has begun) by calling the cancel() method.
def hello():
print "hello, world"
t = Timer(30.0, hello)
t.start() # will print "hello, world" after 30 seconds
t.cancel() # stop it printing "hello, world"

Categories

Resources