Say I have a QListView and each item in this list is meant to be refreshed with the output of a certain system process (such as some intensive file I/O-ing) which is triggered in a thread (using threading.Thread). The problem I have is that the main window's application freezes shortly after I start a new thread and halts the application. Is there a more effective way to achieve this?
It sounds like you should be using QThread rather than threading.Thread.
This question has a lot of useful discussion about how to use threads correctly in PyQt applications.
Related
I want to write a QT program in Python and it is supposed to continuously look for updates. Just like
while(True):
doSomething()
would do in a console based program.
Is there a specific slot which I can connect to for this purpose?
It depends from what you want to achieve.
QThread is one solution.
You also can solve this by using a QTimer with a timeout of zero. Such a timer executes
the connected slot whenever nothing other needs to be done by the event loop (like some background task).
Depending from what you do also a QTimer with a decent timeout can be the solution (like polling for an event).
As I said, it depends from what you want to do.
Use QThread to create loop what your want. Your can find example in here, here and a lot of in google search result. QThread i subclass in QObject so your can connect just like QWidget old-style or new-style signal.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm in the process of converting a simulation based application using simpy into a GUI.
The program currently runs within the console and the simpy which is doing the simulation runs by default in a loop like syntax. And that's where my issue seems to be.
Currently, within the console version of the code, I grab user input through the raw_input() function and that is able to interrupt the code and allow the user to input the values that the simulation desires. However, despite researching it, there does not seem to be a similar and clean way of doing this through pyqt inisde the GUI I'm building.
Would the only way be to run the processes in different threads? And if I were to do that approach, how exactly would that look and truly function?
PyQt is event-based. It's running a loop continuously waiting for events, and it calls your callbacks (or signals your slots) when it gets an event you care about. So, there's no way to directly say "block until I get input".
But, before you even get to that point, if your simulation is running a loop continuously in the main thread, PyQt can't also be running a loop continuously in the main thread. So it can't respond to events from the OS like "update your window" or "quit". As far as your user is concerned, the app is just frozen; she'll see nothing but the ever-popular beachball (or other platform equivalent).
And however you choose to solve that first problem will solve most of the second one almost for free.
Why your GUI app freezes attempts to explain the whole issue, and all of the possible solutions, in general terms, using Tkinter as an example of a GUI library. If you want something more Qt-specific, I'm pretty sure there's a whole section about it in the Qt tutorial, although I'm not sure where, and you may have to translate a bit of C++ to Python in your head.
But there are two major options: Callbacks, or threads.
First, you can break your loop up into small pieces, each of which only takes a few milliseconds. Instead of running the whole loop, you run the first piece, and as its last line, it asks PyQt to schedule the next piece as soon as possible (e.g., using a QTimer with a timeout of 0). Now, Qt will get to check for events every few milliseconds, and if it's got nothing to do, it will immediately kick off the next step of your work.
If your flow control is already built around an iterator (or push-coroutine) that yields appropriately-sized chunks, this is very easy. If not, it can mean turning the flow control in your outer loop inside-out, which can be hard to understand.
So, having done this, how do you get user input? Simple:
Where you would have called raw_input, instead of scheduling the next piece of your code, instead do some appropriate GUI stuff—create a popup messagebox, unhide a text entry control and button, whatever.
Connect the next piece of your code as a handler for the button-clicking or messagebox-accepting or whatever signal.
Alternatively, you can run your work in a background thread. This doesn't require you to reorganize anything, but it does require you to be careful not to share anything between threads. Unfortunately, this includes calling methods on GUI widgets from the background thread, which you'd think would make it impossible to do anything useful. Fortunately, PyQt has mechanisms to deal with that pretty easily: signals are automatically routed between threads as necessary.
So, how do you ask for user input in this scenario?
Split off everything after the raw_input into a separate function, which you connect as a handler for a got_input signal.
In the original function, where you used to call raw_input, you instead emit a gimme_input signal.
Write a handler for that gimme_input signal to run in the main thread, which will put up the GUI widgets (as with the single-threaded example above).
Write a handler for the OK button that emits the got_input signal back to the worker thread.
I have written a little python utility that monitors my typing speed, using pyxhook to hook keyboard events, and a thread timer to update my words per minute number.
Right now it just prints to the terminal every 2 seconds.
How can I make this appear in a little always-on-top gui box?
I tried playing around with tkinter, but the mainloop() function doesn't like my key listener and timer. It seems I can only run the gui OR my event handlers, but not both.
Unfortunately I don't think I can use the keyhandler in tkinter, since I am wanting to capture events from other windows.
Any suggestions?
I don't know how to go about doing this in tk, but I've been using PySide lately and I know you could use that.
One way to do it in pyside would be with two classes running in separate threads that communicate using the Qt signal & slot mechanism available in pyside. One class would subclass QThread & get methods that run your existing code & pass the data via signals to the Ui class. The 2nd class would be the one for your gui elements. it would call for an instance of the first class, connect the signals & slots, then start it & begin drawing the display.
resources if you go the pyside route:
http://www.matteomattei.com/pyside-signals-and-slots-with-qthread-example/
search 'pyside dock widget' on this site
search for github's pyside examples
https://pyside.github.io/docs/pyside/PySide/QtCore/QThread.html?highlight=qthread
I am working on a project coded in python with GUI in Wxpython for last 3 sleepless night now I got struck.Actually inside main parent frame I am executing a new subframe in another thread all I want is to stop further code execution until its subframe has done its work and closed.
I have tried using threading.Thread.join() method but it does not seems to work efficiently and after the Closing of subframe the Main Parent Frame Hangs.
Is there any efficient method to do this thing?
Use a wx.Dialog instead of a sub-frame and its ShowModal() method to stop the execution of the main frame. Technically, you could also use the frame's MakeModal() method for a similar effect, but I think using a dialog makes more sense.
By the way, when using threads with wxPython (or any GUI toolkit), you MUST use the toolkit's threadsafe methods to update the GUI. You should not try to directly access a GUI element from a thread as that is undefined behavior. Instead, use wx.CallAfter, wx.CallLater or wx.PostEvent as they are wxPython's threadsafe methods.
See also:
http://wiki.wxpython.org/LongRunningTasks
http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
I've seen a lot of stuff about running code in subprocesses or threads, and using the multiprocessing and threading modules it's been really easy. However, doing this in a GUI adds an extra layer of complication.
From what I understand, the GUI classes don't like it if you try and manipulate them from multiple threads (or processes). The workaround is to send the data from whatever thread you created it in to the thread responsible for the graphics and then render it there.
Unfortunately, for the scenario I have in mind this is not an option: The gui I've created allows users to write their own plotting code which is then executed. This means I have no control over how they plot exactly, nor do I want to have it. (Update: these plots are displayed in separate windows and don't need to be embedded anywhere in the main GUI. What I want is for them to exist separated from the main GUI, without sharing any of the underlying stack of graphics libraries.)
So what I'm wondering now is
Is there some clean(ish) way of executing a string of python code in a whole new interpreter instance with its own ties to the windowing system?
In response to the comments:
The current application is set up as follows: A simple python script loads a wxPython gui (a wx.App). Using this gui users can set up a simulation, part of which involves creating a script in plain python that runs the simulation and post-processes the results (which usually involves making plots and displaying them). At the moment I'm doing this by simply calling exec() on the script code. This works fine, but the gui freezes while the simulation is running. I've experimented with running the embedded script in a subprocess, which also works fine, right up until you try to display the created graphs (usually using matplotlib's show()). At this point some library deep down in the stack of wxPython, wx, gtk etc starts complaining because you cannot manipulate it from multiple threads.
The set-up I would like to have is roughly the same, but instead of the embedded script sharing a GUI with the main application, I would like it to show graphics in an environment of its own.
And just to clarify:
This is not a question about "how do I do multithreading/multiprocessing" or even "how do I do multithreading/multiprocessing within a single wxpython gui". The question is how I can start a script from a gui that loads an entirely new gui. How do I get the window manager to see this script as an entirely separate application?
The easiest way would be to generate it in a temporary folder somewhere and then make a non-blocking call to the python interpreter, but this makes communication more difficult and it'd be quite hard to know when I could delete the temp files again. I was hoping there was a cleaner, dynamical way of doing this.
Can you simply use subprocess to run 'python.exe' and pipe the script in?
Alternatively, the multiprocessing package should suffice if you want to move some (pickle-able) data over to the new process in which you run the script. Just create a function/callable that runs the script, and create a Process object with the callable as target. That way, you should be able to pass some data over, without having GUI issues.
Capturing text with either is easy, subprocess allows that and no more. With multiprocess, you can pass python objects back and forth more easily.
On Windows, you can create window with a parent window from another process, and draw to that.
See the hWndParent argument to CreateWindowEx.
If wxWindows supports getting/setting that explicitly, then you should be good to go.
Depending on your platform, something similar might be possible in any windows system.
So, just giving your users the ability to find the handle of your apps window should give them the option to plot away at views embedded in your app, while running in their own processes.
I don't no much about wx, I work with jython(python implemented in java and you can use java) and swing. Swing has its own worker thread, and if you do gui updates you wrap your code into a runnable and invoke it with swing.invokelater.
You could see if wx has something like that, if you however are only allowed to manipulate the gui from the thread in which you created it try something similar. create a proxy object for your gui, which forwards all your calls to your thread which forwards them to the gui.
But proxying like this gets messy. how about you let them define classes, with an 'updateGui' function, that they should hand back to you over a queue and that you will execute in your gui thread.
In wxPython land when you use threads, you have to use its thread-safe methods to communicate with the GUI: wx.CallAfter, wx.CallLater or wx.PostEvent. In your case, I would run any long running code in a separate thread/process and when it's done its processing, send the result to the GUI. The GUI can instantiate a new frame and use matplotlib or PyPlot to show the plot, depending on which way you want to go. I've heard you can draw the plot using FloatCanvas too.
Anyway, if you instantiate the new frame correctly, then you can instantiate N frames and show them and be fine. See the wxPython wiki for a few examples of using Threads with wx: http://wiki.wxpython.org/LongRunningTasks