Python: Execute callback method in main thread - python

Not wanting my GUI to freeze, I've decided to use a thread for a file operation. Currently I'm using thread.start_new_thread(self.openFile, (filepath, self.openedFile)) to do so, with self.openedFile being my callback method. Inside self.openFile it is just invoked using callback(success).
But unfortunately I couldn't figure out how to execute my callback in the main thread instead of the newly created one. This is required as the GUI cannot be modified from another thread.
I really appreciate all your help!

The thread owning the GUI will have to periodically check a Queue.Queue instance on which other threads can put work requests (e.g a callback function and arguments for it).
How easy or hard it is to insert such checks within a GUI's main loop is 100% dependent on exactly what GUI framework you're using.
For example if you're using Tkinter, the after method of widgets lets you do such periodic checks, as explained e.g at Run an infinite loop in the backgroung in Tkinter .

Related

Python Threading.Timer is calling command without waiting

I have a very basic Tkinter application that I'm trying to set to automatically refresh. I am using threading.Timer to trigger a function called go at the end of which cocalls the timer to reset it to run again.
def SetTimer():
t=threading.Timer(5,go())
t.start
SetTimer()
I've spent most of my afternoon trying to resolve this but I can't seem to figure out what I'm doing wrong. Based upon the other questions I've read I understand that each instance creates a separate thread with the timer, but why isn't it waiting for the time to elapse prior to triggering the function.
Use:
t=threading.Timer(5,go)
Note the go rather than go(). The parentheses tell Python to call the function. In contrast, go is a function object. Functions are "first-class" objects in Python; they can be passed to functions just like any other object.
Python evaluates the arguments to a function before calling the function. So using go() calls the go before calling threading.Timer. The value returned by go() gets sent to Timer, which is not what you want.
Note that all Tkinter UI code should be called from a single thread. For this reason, using Tkinter's root.after method is probably a better choice for what you want to do. The after method schedules a function to be called by Tkinter's mainloop. Here are some examples using after:
Tkinter and Threads
A rotating image

Checking threadsafe-ness in 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.

How do i call GUI elements in different Qt threads? [duplicate]

I have an application in which a thread (not main thread) needs access to the GUI's elements (send a click action, show a message box, etc). I am working in python and Qt and also know that it is not possible when in not main thread.
Is there a way to do it? I mean to send the action that I want to do in the thread to the main thread.
Here is a good tutorial on how to use Qthread: http://joplaete.wordpress.com/2010/07/21/threading-with-pyqt4/ . This will show how to call the GUI elements in different and custom threads. Hope this helps.

Run function on WxPython GUI thread

part-time C# programmer here trying to learn Python.
I am looking to be able to, from another thread, set up a function that will be run on the GUI thread in WxPython. Currently the only way I can think of doing this is to push the function onto some cross-thread-synchronized list, then have a timer firing every few milliseconds (on the GUI thread) that checks the list and runs any functions that have been pushed onto it. I was wondering if there was instead a more canonical way of doing this, similar to BeginInvoke in .NET.
wx.CallLater and wx.CallAfter().

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