How to set up the thread.Timer without a function? - python

I am working on my code to set up the timer. I want to set up the Timer without creating the function.
Here is what I use:
def hello(self):
print "hello, world"
self.getControl(MyPlayer.Control_EPG_ID).setVisible(False)
def onAction(self, action):
if action.getId() == ACTION_MOVE_DOWN:
t = threading.Timer(5.0, self.hello)
t.start()
I want to make it to show something is like this:
t = threading.Timer(5.0)
t.start()
self.getControl(MyPlayer.Control_EPG_ID).setVisible(False)
when I try it, it give me an error. Do you know how I can set up the timer without create a function? if so how?

You should be able to nest hello() inside of onAction() like this. It will use the self argument passed to the outer function:
def onAction(self, action):
def hello():
print "hello, world"
self.getControl(MyPlayer.Control_EPG_ID).setVisible(False)
if action.getId() == ACTION_MOVE_DOWN:
t = threading.Timer(5.0, hello)
t.start()

Why not like this:
import time
time.sleep(5) # delays for 5 seconds

Related

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"

Python - decorators based execution

I am trying to execute all the functions with common decorator without calling all the functions. For example
#run
#v1
def test1():
#do something
#run
#v1
#v2
def test2():
#do something
#run
#v2
def test3():
#do something
#run
def test4():
#do something
I want to executes the test functions based on the decorators like #run executes all 4 tests. #v1 executes only first two. How can I do that? Any guidance will be helpful.
You could probably use the decorator to "register" your functions in a list:
_to_run = [] # list of functions to run
def run(func):
_to_run.append(func) # add the decorated function to the list
return func
#run
def test1():
print('test1')
return 1
#run
def test2():
print('test2')
def test3():
print('test3')
if __name__ == '__main__':
for test in _to_run: # iterate over registered functions
x = test()
print('Returned:', x)
On the other hand, you could as well create this list explicitly, without decorators.

Log value of variable every second in Python

I need to print the value of a variable every second or couple of seconds, while "at the same time" this variable is being modified. So I would be modifying this variable in my main function and I want something to print its value every second. Something like:
'''This is my main program'''
for i in range(very large number):
'''do something which modifies the value of 'var' '''
And somewhere else in the code:
'''Every second'''
print var
I took a look at this but I'm not sure if it's what I'm looking for, or how I should use it.
What I need is reaaaly simple, there are no other threads, and I don't care about syncing anything, or when in the main function the value is printed.
You can use threading to print var each second.
try this example:
import threading
var = 5
def printit():
global var
threading.Timer(5.0, printit).start()
print "Hello, World!", var
printit()
import time
for i in range(1000000):
time.sleep(2)
var = i
Basically, the question/answer you pointed to is what you need:
import threading import time
interesting = 0
class MonitorThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global interesting
while(1):
print interesting
time.sleep(1)
MonitorThread().start()
for interesting in range(2000000):
time.sleep(1)

How to get a running function's output as an event in Python

I have a question regarding the example posted below...
On my machine calcIt() function takes about 5 seconds to complete.
The same calcIt() function is called from inside of MyClass's callCalcIt() method.
Using while loop MyClass is "watching" for calcIt() function to finish.
Question: A while loop inside of calcIt() method prints out '...running' only once. Honestly I was expecting to see at least 'an infinite loop' type of behavior where '...running' would be printed thousand times per second. Observing a fact the while loop executes a print '...running' line only once makes me believe while loop watches very 'loosely' for calcIt()'s progress. If so, what other (other than while loop) approach should be used to make sure you get what you want: an instant feedback from calcIt() function?
def calcIt():
a=True
while a:
for i in range(25000000):
pass
a=False
return True
class MyClass(object):
def __init__(self):
super(MyClass, self).__init__()
def callCalcIt(self):
b=True
while b:
result=calcIt()
print '...running'
if result: b=False
print 0
calcIt()
print 1
c=MyClass()
c.callCalcIt()
print 2
EDITED LATER:
Posting a revised code with an implementation of solution suggested by Ebarr:
import threading
updateMe=[]
def calcIt():
a=True
while a:
for y in range(3):
for i in range(15000000):
pass
updateMe.append(1)
a=False
return True
class MyClass(object):
def __init__(self):
super(MyClass, self).__init__()
def callCalcIt(self):
thread = threading.Thread(target=calcIt)
thread.start()
print '\n...thread started'
while thread.is_alive():
if len(updateMe)==1: print '...stage 1'
if len(updateMe)==2: print '...stage 2'
if len(updateMe)==3: print '...stage 3'
def printUpdate(self):
print 'updateMe=', len(updateMe)
c=MyClass()
c.callCalcIt()
I'm not sure what you were expecting to happen, but the explanation is very simple. You are running a single threaded code. This means that all of the above will be executed in serial, so there will be no concurrency between the two while loops in your code.
What you appear to be asking is how to thread your code such that you can check the progress of a running function. If that is the case, you can turn calcIt into a thread.
import threading
class CalcIt(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(25000000):
pass
You would then change callCalcIt to:
def callCalcIt(self):
thread = CalcIt()
thread.start()
while thread.is_alive():
print '...running'
Alternatively, you can make it simpler:
import threading
def calcIt():
for i in range(25000000):
pass
def callCalcIt():
thread = threading.Thread(target=calcIt)
thread.start()
while thread.is_alive():
print '...running'
callCalcIt()
I can come up with two ways of doing that, but both require some modification to the calcIt function.
Method 1, callbacks:
def calc_it(callback):
r = 25000000
for x in xrange(r+1):
if not (x % 1000):
callback(x, r) # report every 1000 ticks
class Monitor(object):
def print_status(self, x, r):
print "Done {0} out of {1}".format(x, r)
def call(self):
calc_it(self.print_status)
Method 2, generator:
def calc_it():
r = 25000000
for x in xrange(r+1):
if not (x % 1000): # report every 1000 ticks
yield x, r
class Monitor(object):
def call(self):
for x, r in calc_it():
print "Done {0} out of {1}".format(x, r)
(A side note: in neither case Monitor has to be a class, that's just for consistency with the original code.)
Not sure exactly what you are trying to accomplish, but you could possibly use my newly written generator state machine thingie. Like so:
from generatorstate import State
def calcIt():
while True:
for i in range(25000000):
pass
yield
tick = State(calcIt)
print 0
tick()
print 1
tick()
print 2
I've added a couple of examples, sneak a peek at those if you think it might be a fit.

How to stop an infinite loop on the outside?

Consider the situation: i have the class(third-party library) with method that used infinity loop:
class Worker(object):
...
def transator(self):
...
#if connected print data
while self.connected:
...
print data
if __name__ == "__main__":
worker = Worker()
worker.translator()
I use this class in my program and can not be changed. ( I looked code on github :) ).
What the best method to stop this method manually ? I need change self.connected to False outside this method. I have an idea, but I think it's very complicated.
import time
from threading import Thread
class Terminator(Worker):
...
def terminate(self):
time.sleep(10)
self.connected = False
if __name__ == "__main__":
ter = Terminator()
t = Tread(target=ter.terminate)
t.start()
ter.translator()
Are there other ways?
Q: "How to stop an infinite loop on the outside"
A: Read the documentation for the method/class which is using the infinite loop and look to see if there are any parameters which influence how it runs.
For your use case, it looks to me like you should just be able to pass the timeout parameter to the TwythonStreamer constructor...
Alternatively to mcgilson correct answer you could add a property-descriptor like:
def toggle_connect(self, singleton=[True]):
singleton[0] = not singleton[0]
return singleton
and after:
worker=Worker()
Worker.connected = property(toggle_connect)
You should be able to do something like the following:
import time
from threading import Thread
if __name__ == "__main__":
w = Worker()
t = Thread(target=w.transator)
t.start()
time.sleep(10)
w.connected = False
t.join()

Categories

Resources