Python TKinter for real time GUIs - python

I have written a monitoring program for the control system at our plant. It is basically a GUI which lets the operator see the current status of the lock of the closed loop system and aware the operator in case the lock/loop breaks.
Now, the operation is heavily dependent on the responses of the GUI. My seniors told me that they prefer just the console prints instead of using TKinter based GUI as TKinter has lags while working in real time.
Can anyone please comment on this aspect?
Can this lag be checked and corrected?
Thanks in advance.

I would say that if your program is simply accessing data and not interacting with the data, then a GUI seems to be a bit of overkill. GUI's are guided user interfaces, as you know, and are made for guiding a user through an interface. If the interface is just a status, as you indicated, then I see nothing wrong with a console program.
If, however, your program also interacts with data in a way that would be difficult without a GUI, then the GUI is likely the right choice.
Have you considered a GUI in another programming language? Python is known to be a bit slow, even in console. In my experience, C++ is faster in terms of viewing data. Best of luck!

Python / tkinter in general
In a tkinter program, your code falls in one of four categories;
Initialization code that runs before the mainloop is started.
Callbacks that are run from within the mainloop.
Code running in other threads.
Code running in different processes.
In the first case, the time the code takes only influences the startup time, which for a long-running program is probably not all that relevant.
Concerning the second case, well-written callbacks should not take that long to run. In the order of tens of milliseconds, maybe up to 100 ms. If they take longer, they will render the GUI unresponsive. So unless you notice a sluggish GUI (without threads; see below) this should not be a problem.
One pitfall here are after callbacks, that is functions that will be scheduled to run after a certain time. If you launch them too often, this will also starve the GUI of time.
Another possible problem might be the manipulation of a Canvas with lots and lots of items in it.
As of Python 3.x, tkinter is thread-safe to the best of my understanding. However, in the reference implementation of Python, only one thread at a time can be executing Python bytecode. So doing heavy calculations in a second thread would slow down the GUI.
If you GUI uses multiprocessing to run calculations in another process, that should not influence the speed of your GUI much, unless you do things wrong when communicating with that other process.
Your monitoring program
What is too slow depends on the situation. In general Python is not considered a language suitable for hard real-time programs. To do hard real-time one also needs a suitable operating system.
So the question then becomes what is the acceptable lag in your system specification? Without knowing that it is impossible to precisely answer your question.
It seems that your GUI is just displaying some system status. That should not cause too much of a load, provided that you don't read/check the data too often. As described in the callbacks paragraph above it is possible to starve your GUI of CPU cycles with callbacks that run too often. From what you've written, I gather that the GUI's task is just to inform the human operator.
That leads me to believe that the task is not hugely time critical; a system that requires millisecond intervention time should not rely on a human operator.
So based on your information I would say that a competently written GUI should probably not be too slow.

Related

Incorporation of multiprocessing in pygame

I tried creating a simple game using the pygame module in python. It's a two player game, so it involves getting simultaneous inputs or in other words, events, in the same pygame screen. I tried using multithreading, that is, by running two threads that share a pygame screen, but it didn't work due to the GIL. So, when I tried using multiprocessing instead, I faced a problem in that I couldn't share the same pygame screen. So is there a way to create a pool that has the pygame screen, like there is for sequences? If not, is there any other, perhaps better method to approach my problem? Any answers will be appreciated. Thank you.
You likely don't need either multi-threading and much less multi-processing there.
What do you mean by "it didn't work due to the GIL"? Did you get any error message when trying to do multi-threaded?
It is possible to create a naive multi-threading design that could facilitate updating objects controlled by different players, but some care would have to be taken anyway. The GIL should only impact you that you really would have no benefit like using more than 1 core in your application, but won't give you any errors.
As for using multi-processing, the secondary process would not be able to use the screen Surface anyway, and passing surfaces (images) across process is mostly not worth it (if it is feasible at all).
I meant that when I pressed a button, only one of the threads detected
key down. I did not get any errors. It is due to GIL right? I'm sorry
if I'm wrong.
No - this does not have to do with the GIL in any way -- it has to do with the pygame event API not having being designed to work with threads.
There are two ways of dealing with key-presses in Pygame: either checking for KEYDOWN events, or calling pygame.key.get_pressed. I usually prefer the second due to it not depending on key auto-repeating settings at the OS or BIOS level (unless, of course, it is an action that is to be executed just once, and not while a key is pressed).
Anyway, in any pygame related project, you should check for pygame events (key presses included) in a single place in your code, and on the same thread. Once you have the information you need from the "outside world", you can set your internal variables as you want.
But, since you don't offer any code, the most direct fix I can suggest to your multi-threaded code is to use get_pressed instead of checking for events: it will likely work from both threads. (the multi-processing code would be much more complicated than that).

Using Time in Python

I rewriting a simple midi music sequencer from javascript into Python as a way of teaching myself Python.
I'm ready to begin working with time (for fireing midi events) but I can't find any good resources for executing scripts in time, scheduling timing events, etc.
A few things I've read suggest I should use a module like tkinter, but I would rather have all the timing mechanisms independent of any gui module.
Does anyone have any suggestions/resources for working with time?
For executing scripts in a certain interval (of course within another script), you might want to take a look at the time module (Documentation here).
But if you are planning to use timing with a GUI, you might want to have concurrent threading or processing so that there is not delay with the user interface. In such case you can use multithreading (Documentation) or multiprocessing (Documentation) modules.
As a final note, some GUI frameworks come with built-in threading support, so you might want to take a look at that. For example, PyQT4 has something called QThread which handles all thread/event manipulation.

Writing data so repeatedly in SQLite Database with python

I want to use SQLite for my GUI Python application but I have to update database every 500 MS without effecting the performance of my program.
I'm using PyQt4,So I thought about using QThread but it seems difficult to deal with, so I wondered if it was the best way before really trying to understand it.
My Question is: is QThread the best way or there are other ways?‬
According to the fact that python implementation rely on the GIL, even with using threads or timer you won't be able to do something (potentially costly) in your program without effecting the global performance of the program.
I will suggest you to have a look to multiprocessing module to get around of this limitation. Using this module, you will no more use threads (that are affected by the GIL), but processes (not affected by GIL).
Maybe you could create a subprocess that will arm a timer to make the update every 500ms when the main process will continue his job.
Then, you will let the system do the job of balancing the programs and it may be better in term of responsiveness (especially in a multi core environment)

Is using multiple Timers in Python dangerous?

I am working on a text-based game in Python 3.1 that would use timing as it's major source of game play. In order to do this effectively (rather than check the time every mainloop, my current method, which can be inaccurate, and slow if multiple people are playing the game at once) I was thinking about using the Threading.Timer class. Is it a bad thing to have multiple timers going at the same time? if so, how many timers is recommended?
For example, the user inputs to start the game. every second after the game starts it decides whether or not something happens, so there's a Timer(1) for every user playing at the same time. If something happens, the player has a certain time to react to it, so a timer must be set for that. If the user reacts quickly enough, that timer needs to end and it will set a new timer depending on what's going to happen next, etc
I think its a bad idea to use Timers in your case.
Using the delayed threads in python will result in more complex code, less accuracy, and quite possible worse performance. Basically, the rule is that if you think you need threads, you don't. Very few programs benefit from the use of threads.
I don't know what you are doing for input. You make reference to multiple players and I'm not sure whether thats on a single keyboard or perhaps networked. Regardless, your current strategy of a main loop may well be the best strategy. Although without seeing how your main loop operates its hard to say for certain.
It should be perfectly safe to have multiple timers going at the same time. Beware that it may not give much of a performance boost, as the CPython interpreter (the standard Python interpreter) uses a GIL (Global Interpreter Lock) which makes threading stuff a bit.... slow.

How to work with threads in pygtk

I have a problem with threads in pygtk. My application consist of a program that downloads pictures off the internet and then displays it with pygtk. The problem is that in order to do this and keep the GUI responsive, I need to use threads.
So I got into a callback after the user clicked on the button "Download pictures" and I call the method to download the pictures that is within that same class.
thread.start_new_thread(self.images_download, (path,pages)
This won't work. The only way I get my program to get into the thread is by using
gtk.threads_init()
Before starting any thread. Now it downloads the pictures but the GUI remains unresponsive.
I googled this and I tried putting gtk.threads_enter and gtk.threads_leave around the threads but it just doesn't work.
Your question is a bit vague, and without a reference to your actual code it's hard to speculate what you're doing wrong.
So I'll give you some pointers to read, then speculate wildly based on experience.
First of all, you seem to think that you can only keep the GUI responsive by using threads. This is not true. You can also write your code asynchronously, and do everything in a single-threaded application. Twisted is built on this programming model. I recently made a blog post that explains how I created an asynchronous task interface, and example runners both for CLI and GTK+. You can look at those examples to see how tasks can be implemented asynchronously, and the UI still gets updated.
Second, if you prefer to use threads for some reason, you will need to understand the GTK+ threading model a little.
You should start by reading The PyGTK FAQ entry on the subject, and you might find this blog post easy to understand too.
Now, on to speculation. I am guessing that you are trying to update your GTK UI from the thread, and not handling the locking properly. If this is the case, you are better off for now deferring all your UI updates you want to do from threads to the main thread by using gobject.idle_add() This way, all UI calls will be made from the main thread. It is an easier mental model to follow in your programming.
Once you feel you really understand the threading and locking models, you could consider updating the UI from your threads, but it's easy to miss a threads_enter()/threads_leave()
You can use gtk.gdk.threads_init() in order to allow any thread modify the UI with the respecting gtk.gdk.threads_enter() and gtk.gdk.theads_leave() lock, but, the problem with this is that doesn't work well on windows. I have tested it on Linux and performs quite well, but I had no luck making this to work over win32.
=== Edit ===
I have been browsing about this, you could make use of the gobject.io_add_watch to check if there is something in your socket, grab it and then update the GUI. check my post about this:
Sockets (and some other files) and PyGTK without threads.

Categories

Resources