Checking threadsafe-ness in python? - python

This is my first foray into threading, so apologies for any obvious mistakes.
I have a PyQt widget, from which a new process, prog, is run in a different thread. In my main thread, I'm also redirecting stdout to a read-only QTextEdit. However, I get errors referring to recursion, and I'm worried that my threads are interfering in each other in a way which causes a print statement to go into an infinite loop. I only get these errors if I run prog from the GUI, and not from the command line. My stdout redirect is using the code in this SO answer
In pseudo-code, this is basically what I've got:
gui.py
class widget(QWidget):
def __init__(self):
self.button = QPushButton("GO!", self)
self.button.clicked.connect(self.start)
def start(self):
self.thread = TaskThread()
sys.stdout = EmittingStream(textWritten = self.outputText)
self.thread.start()
def outputText(self):
#as in answer provided in link (EmittingStream in separate module)
prog.py
class TaskThread(QThread):
def run(self):
'''
Long complicated program; putting in simpler code here (e.g. loop printing to 10000) doesn't reproduce errors
'''
Is there any way of finding out if my recursion is caused by an infinite loop, or by anything else?
Is my code obviously thread-unsafe?
How do you make functions guaranteed to be threadsafe? (Links to tutorials / books will be good!)

This is tricky, but I think that your code is thread-unsafe. Specifically, looking at other stackoverflow answers (here and here) it appears that you should not be accessing a Qt GUI object from another thread than the one it was created in (even a QThread).
Since any call to print in your code now accesses a Qt GUI object, it seems this is very thread unsafe.
My suggestion to make it safe would be to:
Have a QThread, inside of which you have instantiated the output box (it is thread safe to access a Qt GUI object from the thread it was created in, and it does not have to be created in the main thread) Qt GUI objects are not reentrant and must be created and used in the main thread only, see here As such you will need a QThread to post events back to the main thread (using the Qt signals/slots mechanism which can be thread safe when done correctly)
Have this QThread blocking on reading from a Python Queue. When it gets something from the queue, it places it in the Qt text box posts it back to the main thread, and the main thread will update the output box.
Modify your EmmittingStream to place things in the Queue, rather than directly into the Qt output box.

I can see you have located where the error is. But without the code there is not much that I can tell.
Filling your needs of direction, I'll point to you to Python profiles. Since it looks like you need some python profiling tools.
http://docs.python.org/2/library/profile.html
and a answer about the subject
How can you profile a Python script?

In a Qt application you must use one single thread to handle the all the gui part. You can use other threads for computations, but not for user interface.
Just post messages about updates in a queue in the worker threads and use the main thread to pick up those messages and update the GUI.

Related

QT Designer Qmessagebox GUI Hangs in Thread

GUI blocks and shows error in VS Code
Error: QObject::setParent: Cannot set parent, new parent is in a different thread.
and this is code !
def ok_handler(self):
try:
xmpp = Bot(self.uname.text() + '#', self.password.text())
except InvalidJID:
QMessageBox.about(self, "Error !", "Enter User Details")
def threadstart(self):
Thread(target=self.ok_handler).start()
any solution?
Provide solution how to show QMessageBox in thread.
In Qt, Gui operations are handled only in the main thread as I know. If you are running a thread, via signal&slot(thread safe approach) you can trigger a slot in the main thread of the application and show the messagebox.
For example, if you are reading a file, gui operations should be done in the main thread. You can click a button which triggers a file reading method in a different thread and opens a message box which says "Wait until load". in the main thread. When file reading ends, file reading thread can trigger a slot in the main thread which closes the messagebox.
As a result; all gui operations should be done in the main thread but in order not to block the gui, jobs like file reading and networking should be done in a different thread.
Multiple comments about your code, linked to the documentation here.
Your error message is about creating an object with a parent that lives in another thread. This is forbidden.
Quote: The child of a QObject must always be created in the thread where the parent was created.
The underlying reason why this is forbidden is because when an object is destroyed, it deletes all its children. If that were to happen across several thread, you would likely end up deleting an object in thread 1 while it is being used in thread 2. I hope I do not have to explain why that would be a bad thing.
Subclasses of QWidget can only be created from the main thread and cannot be moved to another thread. This is an additional restriction that "regular" subclasses of QObject are not subject too.
Quote: Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread. As noted earlier, QCoreApplication::exec() must also be called from that thread.
The reason for that is completely different: Qt works on a variety of OS, some of which allow GUI to live only in the main thread. For that reason, moving subclasses of QWidget to worker threads was disabled on all OS.
The solution for you is actually simple:
It is optional (I think/hope) but I strongly recommend you create a worker object to handle the work that happens in the thread.
Create a slot in your main class in charge of showing the QMessageBox.
Define a signal (e.g. errorOccured(QString)) in your worker class; replace QMessageBox.about(...) with it.
Connect the signal to the slot, with a Qt.QueuedConnection (this part is important) before the thread is started.

python threads gui

I have a small issue when working with PyQt4 and threading package:
My code looks like this:
def goForwardToSamples(self):
self.main.dataSet = DataSetProvider(self.main.sourceFile)
self.ui = Ui_NeuralPredictor2()
self.ui.setupUi(self)
ParalelGui(self.ui).start()
self.connectSignalsWindow2()
def connectSignalsWindw2(self):
# DOING SOME REAL SERIOUS COMPUTATION ...
=> now def run(self): in ParalelGui class looks like this:
def run(self):
self.gui.show()
=> I just want to test if my GUI will run paralel with the computation.
I feel I know what the problem is. I have a QtableView that is being filled with data where I wrote (DOING SOME REAL SERIOUS COMPUTATION..). That QtableView is of course part of ui that I am sending to ParalelGui thread to be shown. I am not really sure how to make it work... Basically I would like to have a part of GUI threaded and already shown while the other part is being filled up dynamically in different thread.
What happens now is the typical 'you didnt thread your gui freeze' ... help much appreciated
Even though your example is highly limited, I am going to take a stab at what I think you are doing here...
To me, it seems like you are doing things backwards and trying to show your gui in a thread while doing heavy computation in your main thread?
What you really should be doing is creating and showing your gui in the main thread, and running heavy computation in a separate worker thread. This worker thread can then emit a signal when data is ready, which your main thread can connect to and quickly update your table. This way you don't block your main thread. The rule of thumb is never do anything heavy in the main thread. Its meant for the GUI and its events.
Also, make sure you are using the QThread class and not the python threading module.

Detecting the module in python (which sends data to the GUI thread)

So I wrote this software which used to implement 4 tabs (now 8). Now, every tab is its own QThread, plus one general GUI thread, obviously. The worker threads (tab threads) send data back to the GUI thread when this needs updating. For example, I have a statusBar text in the GUI thread which needs to be updated every time worker thread does something. I'm using the SIGNAL/SLOT for that, and the way I detect an incoming SIGNAL is like this:
def setStatus(self, status):
#Defining SIGNAL sender
self.sender = QObject().sender()
if "module1" in str(self.sender):
self.module1CurrentStatus.setText(status)
Now this works and all, but like I said, the software has grown from implementing 4 tabs to implementing 8 tabs. Is there a better way to implement this, instead of using sender()? I'm simply looking for something that can be written only once for all the modules, a way for the GUI to know automatically which thread the SIGNAL came from. I know that I could write a separate SIGNAL for every module, but I accomplish nothing with that.
If I understand your requirements correctly, you could use a QSignalMapper to re-emit the signals with an identifier.
The module name can be acquired via __name__, unless it is the file being run as a script .

WX.Python and multiprocessing

I have a wx.python application that takes some files and processes them when a button is clicked. I need to process them in parallel.
I use this code inside the bound button function:
my_pool = multiprocessing.Pool(POOLSIZE)
results=[digest_pool.apply_async(self.fun, [args]) for file in list_files() ]
my_pool.close()
my_pool.join()
for result in results :
print result.get()
But it seems this code is not run at all, even if I print something on fun. I didn't get any result and my GUI application got stuck. Could someone help? What is the problem here and how can I solve it using the pool multiprocessing module inside my wx frame class?
It looks like you're running up against a pretty common problem encountered by people attempting to use threading with GUI toolkits. The core of the issue is that you must never block the main GUI thread in your code. The graphical toolkit needs to be able to constantly respond to events. When you do the my_pool.join() call, you're putting the main thread to sleep and the result is that your entire process will appear to lock up.
I'm not particularly familiar with wxWidgets but I'm sure there are a few patterns out there for how to use threads with it. It's easy to spin off background threads from the GUI thread but getting the results back is usually the trick. You'll need some sort of asynchronous "work done" event that you can send to the main GUI thread when the background operation completes. Exactly how that's done differs from toolkit to toolkit. I'm not sure what the mechanism is for wxWidgets but I'd expect a quick google search would turn up an answer (or perhaps a kind commenter will provide a link ;-)

PyQt4 Threading: Sending data back to a thread

I'm writing a program, with a PyQt frontend. To ensure that the UI doesn't freeze up, I use QThreads to emit signals back to the parent. Now, I have reached a point where I need my thread to stop running, emit a signal back to the parent, then wait on the parent to return an approval for the thread to continue (after the user interacts with the UI a little bit).
I've been looking into the QMutex class, along with QThread's wait function.
How should I go about doing this properly?
One approach is using a condition variable.
In my code, however, I prefer using Python's built-in Queue objects to synchronize data between threads. While I'm at it, I use Python's threads as opposed to PyQt threads, mainly because it allows me to reuse the non-GUI part of the code without an actual GUI.

Categories