pylab not properly working when embedded into Qt
Hi! I try to embed python into a Qt C++ application. I don't need any speciality, just run some prepared scripts from time to time. E.g. I have a function which should do some plotting through pylab. When I call this function ("run", see below) from the main (GUI) thread, everything works fine and as expected. But as soon as I spawn a new thread to run this function in it, it stops to work ('hangs' forever?) Strangely, the problem only shows up when I call 'import pylab'. It seems everything else which I tested (all other non-pylab related python code) works fine even when executed from any thread. I need to run the python scripts in a different thread than the main thread (which also controls the GUI) to keep the application responsive while running longer scripts. int run() { Py_Initialize(); PyGILState_STATE state = PyGILState_Ensure(); PyRun_SimpleString("import pylab; pylab.plot([1,2]); pylab.show();"); PyGILState_Release(state); Py_Finalize(); } // the function from the Qt GUI-thread (main thread) works fine // (with any python string in PyRun_SimpleString() ) run(); // but this blocks forever at 'import pylab' std::thread t = std::thread(run); t.join(); (I call Py_Initialize only once in the program) Could this be a threading issue? I don't think so, because even when the qt app uses multiple threads, only one of it accesses python variables. It seems to me, pylab does not like it when another thread controls the GUIs!?! Is there a work around/fix? What do I miss? I tried putting Py_Initialize/Py_Finalize also into the main thread, but it didn't made any difference. Many thanks for any hints! Regards, Jan
Just to make sure, pylab.show() interacts with the GUI, right? Most GUIs, including Qt if I remember right, are not multithreaded, meaning you've got one GUI thread running the GUI main event loop, and any manipulation of the GUI does need to happen from there. (One usually has mechanisms to inject events/work into the event loop, and to push out work into other threads, ...) My recommendation would be to run it with three separate PyRun_SimpleString() and see where it blocks. Some locking considerations: * import does internally locking. * If pylab.show() does use Qt GUI functionality, it will almost burn (that can also include failure modes like blocking) for sure. * If pylab.plot() is the long running thing, then consider calling pylab.plot() in a separate thread, and when done pylab.plot() in the GUI/main thread. The usual way to keep a GUI responsive during long work, if work involves the GUI is to make "yield to process GUI events" calls in you inner loop. (the exact naming depends again on the GUI). This way the GUI is handled and stays responsive, while your work can proceed. Regards, Andreas The information contained in this e-mail message is privileged and confidential and is for the exclusive use of the addressee. The person who receives this message and who is not the addressee, one of his employees or an agent entitled to hand it over to the addressee, is informed that he may not use, disclose or reproduce the contents thereof, and is kindly asked to notify the sender and delete the e-mail immediately.
participants (2)
-
Jan Müller -
Kostyrka (External user) Andreas