I'm writing a short application in python using tkinter. Everything works except for an unexpected pause - it should be generating an event twice a second, but frequently it will pause for 5 or 6 seconds between signals. I've put print statements to find where the delay is, and found it is the following statement:
self.frame.after(ms, self.tick_handler)
ms is 500 so this should send the event at around .5 seconds. Usually it does, but frequently it hangs for as much as 5 or 6 seconds before tick_handler() gets the signal. The program is pretty simple, with a single worker thread receiving all input from a single queue, events coming from a single tkinter frame. The after() statement is in the worker thread. I've tried shutting off gc (gc.disable()) but that makes no difference. There is minimal activity outside this on my computer.
If I send other input during the pause using mouse or keys it is handled immediately, so the worker thread is not blocked. It looks as if the signal request is received but not fired for some time. I know I can't expect real time performance so .6 seconds wouldn't be noteworthy, but 6.0 seconds?
This is the first time I've worked with tkinter. Is there something I am missing about event handling?
I Think You Did Not Include tkinter.mainloop() At The End
PS: I'm Not Sure...
When using the after method in tkinter, instead of doing root.after(function_name,time_delayed) do root.after(function_name(),time_delayed) as this worked for me and the delay disappeared.
Related
I'm writing a program to control GPIO's on my raspberry pi. I would like my program to ask me how long I would like to keep a GPIO on before it turns off.
Is it possible to have it stay on for 1 hour and then turn off. The problem I'm having is that when its on for an hour I cant issue any other commands to turn on other GPIO's because sleep.time is still being processed. I'd like to set multiple GPIO's for different times at the same time.
There are many ways to solve the problem. Conceptually, instead of sleeping 30 seconds and then doing something, you can sleep one second, do a bunch of stuff, check the time, lather, rinse, repeat. And by "sleep one second" it could just as easily be a tenth of a second or five seconds or whatever seems reasonable to me.
Another solution is to create a second thread (or process) for this sleep command so that your main thread (or process) runs unabated.
The choice depends on what all you need to do, how accurate you need the delay to be, what other things are running on the system, and so on.
Your current script only have one thread running, the sleep() will put the current running thread into sleep mode which blocks further commands.
time.sleep(secs) Python Doc
time.sleep(secs)
Suspend execution of the current thread for the given number of seconds.
You will need one more thread on the background which keeps the timer for you. In the mean time, the thread on the foreground can still takes other commands.
I recommend you read this page
threading – Manage concurrent threads
I have a project using two Raspberry Pis, where one should send the control signals to the other one, which should recieve and process them to control some Servomotors accordingly, all done in Python.
Now that is not a problem for me, but the problem lies in recieving the signals:
The method I use to ensure long ranges, needs to be in sync perfectly and has a timeout period. If it is not perfectly in sync, it waits for the signal and can stop the whole program for approx. 5 seconds or so.
Now, is there any possibility to let the checking and the moving be done at the same time, so that the movement stops when the signal says to stop but at the same time the checking does not interrupt the movement?
-Chrono
I have a Python 2.7 program running an infinite while loop and I want to incorporate a timer interrupt.
What I aim to do is to set off a timer at some point in the loop, and when 5 seconds have elapsed I want the code to branch to a specific part of the while loop.
What I have been doing so far is the following:
in each iteration of the while loop I am checking how much time has elapsed when I reach that point in the code using
time.clock()
and if the difference exceeds 5 I run the chunk of code I mean to run
However that way 7 seconds might pass before I evaluate the time, it will be >5sec but I want to go there exactly when 5 seconds pass
Also, I need this to work for more than 1 counter (possibly up to a 100) but I do not want the interrupts to interrupt each other. Using Timer did not work either.
I know this can be done using timer interrupts in assembly but how can I do that in python?
If a single event is to be handled, then the easiest way is to use the signal framework which is a standard module of Python.
However, if we need a fully-fledged scheduler, then we have to resort to another module: sched. Here is a pointer to the official documentation. Please be aware, though, that in multi-threaded environments sched has limitations with respect to thread-safety.
Another option is the Advanced Python Scheduler, which is not part of the standard distribution.
You can't get real-time without special hardware/software support. You don't need it in most cases (do you need to control giant robots?).
How to delay several function calls by known numbers of seconds depends on your needs e.g., if a time it takes to run a function is negligible compared to the delay between the calls then you could run all functions in a single thread:
#!/usr/bin/env python
from __future__ import print_function
from Tkinter import Tk
root = Tk()
root.withdraw() # don't show the GUI window
root.after(1000, print, 'foo') # print foo in a second
root.after(0, print, 'bar') # print bar in a jiffy
root.after(2000, root.destroy) # exit mainloop in 2 seconds
root.mainloop()
print("done")
It implements yours "I do not want the interrupts to interrupt each other either" because the next callback is not called until the previous one is complete.
Basically I am using toasterbox and I want code to run, lets say every 30 seconds. Well every 30 seconds the toasterbox should pop up. The code looks like this
event = threading.Event()
#############################################
bWidth = 200
bHeight = 100
tb = TB.ToasterBox(self, TB.TB_COMPLEX, TB.DEFAULT_TB_STYLE, TB.TB_ONTIME)
tb.SetPopupSize((bWidth,bHeight))
tb.SetPopupPosition((1600-bWidth,900-bHeight))
tb.SetPopupPauseTime(4000)
tb.SetPopupScrollSpeed(8)
##############################################
while true:
showPopup(tb,name,amount,progress,link)
tb.Play()
event.wait(30)
That should give you an idea. Anyway the problem that occurs is, the toasterbox pops up but tb.play() isn't blocking because it spawns a timer to handle animation so the thread immediately continues to the wait function and blocks, so the toasterbox never closes. Is there a way to change the code for play to make it blocking? Or is there a better way to do this. I tried creating a new thread to run tb.play() in but it threw an error about only being able to run from the main thread. More info about toaster box including the source found here: Toasterbox
What is this toasterbox you're using? There's one included with wxPython. See here http://xoomer.virgilio.it/infinity77/AGW_Docs/toasterbox_module.html#toasterbox or here http://www.wxpython.org/docs/api/wx.lib.agw.toasterbox.ToasterBox-class.html
I don't think the agw one supports blocking and I'm guessing the one you're using doesn't either. You can ask on the wxPython mailing list to see if they can patch their version or have a better suggestion. Personally, I would use a wx.Timer to pop up the toaster. That should take care of your problem without threads. There's an example of how to use timers here: http://www.blog.pythonlibrary.org/2009/08/25/wxpython-using-wx-timers/
I have a wxPython application that uses pyinotify (via ThreadedNotifier) to check when a certain file gets modified. When this happens, the application stops watching the file and does some stuff. Everything works fine, except that often the call to ThreadedNotifier.stop() takes a noticeable time, about 4 seconds... Other times, it exits immediately.
Anyone else experienced this? Is this expected?
(Xubuntu 9.04)
Could it be that it is a polling mechanism with a timeout of about 4 seconds? And that the thread is only really stopped when it is entering the run() stage?
That might have something to do with the threading library.
You could test that by using a notifier with a different timeout.