jeanc
jeanc

Reputation: 4833

nonblocking timer in python

I am developing an app in python with pyGtk+Glade.

I want to execute a function every N seconds (just like in javascript the function setTimeout()). If the user perform a click, some action must be done, and the timer must be reset.

I was trying with threading.Timer, something like this:

def callback():
    print "callback executed"

t = threading.Timer(10.0, callback)
t.start()

but it doesn't work for me because it blocks everything for the N secs and doesn't capture the user click.

Any other option?

Upvotes: 3

Views: 1955

Answers (2)

unutbu
unutbu

Reputation: 879123

This creates a timer which calls MainWin.update() every second. When the button is pressed, the current timer is killed and a new timer is started.

import pygtk
pygtk.require('2.0')
import gtk
import gobject
import time

class MainWin(object):
    def destroy(self, widget, data=None):
        gtk.main_quit()
    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("destroy", self.destroy)
        self.window.set_border_width(10)
        self.button = gtk.Button("Reset")
        self.button.connect("clicked", self.onclick)
        self.window.add(self.button)
        self.button.show()
        self.window.show()
        self.reset_timer = False
        self.count = 0
        self.duration = 1000
        self.timer = gobject.timeout_add(self.duration, self.update)
    def reset(self):
        print('Resetting timer')
        gobject.source_remove(self.timer)
        # start a new period call to update
        self.count = 0        
        self.timer = gobject.timeout_add(self.duration, self.update) 
    def onclick(self, widget):
        # Every action which resets the timer should call self.reset_timer().
        self.reset()
    def update(self):
        print('{t:.1f}: count = {i}'.format(t=time.time() % 100, i=self.count))
        self.count += 1
        return True
    def main(self):
        gtk.main()

if __name__=='__main__':
    MainWin().main()

Upvotes: 0

Bren
Bren

Reputation: 124

Since you're using PyGTK, your program should probably be using the g_main_loop, in which case you can call glib.timeout_add (interval, callback) to add a callback that gets called (roughly) every X seconds.

Here's an example:

import glib
import gtk

def yo ():
    print "yo"
    return True

glib.timeout_add (1000, yo)
gtk.main ()

Unfortunately, to reset the timeout I couldn't come up with an elegant solution. But you can create your own main loop so you have control over when the timeout resets, sorta like this:

import glib
import gtk
import time

timeout = 1;
timer = time.time() + timeout
while (True):
    gtk.main_iteration (False)
    if (timer <= time.time()):
        print "Time up!"
        timer = time.time() + timeout

Upvotes: 2

Related Questions