Menu

running a thread-based python script from PythonQt

Help
Mortie
2019-01-17
2019-09-06
  • Mortie

    Mortie - 2019-01-17

    Hi
    I've used r502 version of PythonQt with thread support, I wanted to run a special simple script below but I'm getting crashed when I want to run it from PythonQt framework:

    class myWidget(threading.Thread):
        def __init__(self):
            threadin.Thread.__init__(self)
        def run(self):
            widget = Qt.QWidget()
            widget.show()
    w = myWidget()
    w.start()
    

    I've set
    PythonQt::setEnableThreadSupport(true)

    it gives me the errors like below (in some somehow same situtuation with a little twerk):

    1:

    Cannot set parent, new parent is in a different thread
    

    2:

    ASSERT failure in QWidget: "Widgets must be created in the GUI thread."
    

    3:

    ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 00x0x2e14e370. Reciever 'QWidgetClassWindow' (of type 'QWidgetWindow') was created in thread 0x0x60d3b3a0"
    

    is there something else I should do? so I can get a python thread running in my script to work fine?

     
  • Florian Link

    Florian Link - 2019-01-17

    Qt does not allow to create widgets outside the GUI thread, this a Qt limitation, not a Python limitation.

     
  • Mortie

    Mortie - 2019-01-20

    Thank you Florian for your attention and reply
    I've managed somehow to make a debugger with PythonQt and bdb library of python.
    the problem is that bdb or other python debuggers are thread-based and if I use PythonQt_QtAll GUI elements it will be trapped in the thread of python I think and will crash out to desktop when stepping over script lines.
    do you have any suggestion for a way that I can manage it to work or any other efforts that I should follow maybe?

    Regards

     
  • Florian Link

    Florian Link - 2019-01-20

    I think you have to look into remote debugging, e.g. like in PyDev /Eclipse or PyCharm.
    Running a debugger in the same process with Qt Gui is not possible, because the main thread will be blocked, so your Gui can't update. You need a second process which shows the Debugger and has a UI, typically that application is the text editor as well, so that you can set breakpoints and show where the cursor is located. Maybe using an existing remote debugger would be a simple solution for you (but less integrated and customized, of course).

     
  • Mortie

    Mortie - 2019-01-20

    Thank you so much
    right now I don't have any problem in debugging a GUI-less script like even working with models and other libraries of Wrapped Qt classes and it works fleuntly. I developed a UI with text editor, highighting syntax, breakpoints and any other concepts required by a simple debugger like variables table etc. but when it comes to the wrapped GUI classes it will shoot a fatal error to screen when I'm stepping over the commands related to the GUI.
    so do you mean I can also debug GUI-based script lines with a remote debugger?
    is there some example for the way you suggested to implement a multi-process application to attach a debugger to the script from another process? right now I just have 2 threads in my debugger component , one for GUI and one for debugging with bdb. but I still recieve the error.

     

    Last edit: Mortie 2019-01-21
  • Mortie

    Mortie - 2019-01-27

    I've tricked this task by using queued signal and slots mechanism for GUI components that are going to be debugged. so the wrapped methods will just rise a signal and it'll catch it's appropriate method by pre-defined connections with Qt::AutoConnect so GUI components will decide how to connect to those relative slots based on the method they're running. (debug or just runeval)
    I know this is not a professional method for doing these stuff but it just satisfies my needs until now.

     
  • Max

    Max - 2019-09-02

    So, in 2019 closing to the end, what is the status of threading module support in PythonQt? I see the PythonQt::setEnableThreadSupport(true) method in the docs, and I call it when my app starts. Nevertheless, when I start threads in embedded interpreter, they are not working as expected. NOTE: I am not asking for help - just a short answer if threading is supported in last version of PythonQt (as suggested by the existence of the above-mentioned method) or not.

    P.S. Below is the code I use in python. If started from PythonQt embedded interpreter, only one line running... is shown.

    import time
    from threading import Thread
    class MyThread(Thread):
        def __init__(self):
            super().__init__()
    
        def run(self):
            while True:
                print("running...")
                time.sleep(0.2)
    
    t = MyThread()
    t.start()
    
     

    Last edit: Max 2019-09-02
  • Florian Link

    Florian Link - 2019-09-02

    Threading in PythonQt in fully functional and working.
    There is one thing that you have to keep in mind:
    By default, the main thread of your application will hold the GIL, so other threads can only get a time slice when the main thread is running in a Python loop.
    So what you have to do is to release the GIL after you started up PythonQt and retake it whenever you want to talk to Python from C++ from whatever thread.

    You release the GIL after the initial PythonQt initialization by:

    PythonQt::setEnableThreadSupport(true);
     // release the GIL until we finalize Python
     PyThreadState* state = PyEval_SaveThread();
     // after this, don't talk to Python or PythonQt without retaking the GIL, either with PyEval_RestoreThread(state) or with PYTHONQT_GIL_SCOPE scope object.
    

    There is a macro for taking and releasing the GIL, called PYTHONQT_GIL_SCOPE, place this at all code that talks to PythonQt or Python itself.

     

    Last edit: Florian Link 2019-09-02
  • Max

    Max - 2019-09-06

    Thanks for your help. The problem was that I am using PythonQtScriptingConsole, and after releasing the GIL, the app seg-faulted whenever I just typed into the console (without even pressing Enter). But if I do not interact with the console but just evaluate a script from my c++ app, then python threads run normally without blocking my c++ app. (Still, it's a bit surprising that seg-fault happens when I type a single letter in the console -- is python interpreter invoked without even pressing Enter?).

     

    Last edit: Max 2019-09-06
  • Florian Link

    Florian Link - 2019-09-06

    yes, for autocompletion. I have not yet adapted toconsole, becausewe have our own console in our product. It just needs additional GIL scope locks to work with threading.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.