Why am I unable to run a PySide GUI in a spawned child process?



  • I just posted this to stackoverflow, but perhaps someone here will be able to help.

    I'm attempting to run a PySide GUI in a spawned child process, but it keeps exiting with exitcode 11 (segfault). This simplified test code works fine if run_gui is called directly, but fails if it's run inside a child process:

    @# std lib imports
    import time
    import sys
    from multiprocessing import Process

    third party imports

    from PySide.QtGui import QApplication, QMainWindow

    def run_gui():
    app = QApplication([])
    w = QMainWindow()
    w.show()
    w.raise_()
    sys.exit(app.exec_())

    def main():
    gui_proc = Process(target=run_gui)
    #gui_proc.daemon = True # this doesn't seem to matter
    gui_proc.start()
    while True:
    if not gui_proc.is_alive():
    if gui_proc.exitcode != 0:
    print 'GUI exited with code {}'.format(gui_proc.exitcode)
    else:
    print 'GUI exited cleanly.'
    break
    time.sleep(1)

    if name == "main":
    ## GUI in main process:
    #run_gui()
    ## GUI in child process:
    main()@

    Is there a way around this? I'm not sure how to debug what's causing the segfault.

    The reason I'm interested in doing this is so that I can restart the GUI if it crashes unexpectedly, all the while keeping a couple daemon processes running (one for disk access and another for interacting with instruments).

    I also tried another test script (below) using QCoreApplication and no GUI, and I see the same problem. Apparently PySide just won't run in a child process.

    @# std lib imports
    import time
    import sys
    from multiprocessing import Process

    third party imports

    from PySide.QtCore import QCoreApplication, QTimer

    def quit():
    print "Quiting..."
    sys.exit()

    def run():
    app = QCoreApplication([])
    timer = QTimer()
    timer.timeout.connect(quit)
    timer.start(1000)
    print "Starting..."
    sys.exit(app.exec_())

    def main():
    proc = Process(target=run)
    #proc.daemon = True # this doesn't seem to matter
    proc.start()
    while True:
    if not proc.is_alive():
    print 'Process exited with code {}'.format(proc.exitcode)
    break
    time.sleep(1)

    if name == "main":
    ## GUI in main process:
    #run()
    ## GUI in child process:
    main()@



  • My experience (with PyQt) is that Qt doesn't always play nice with Python's multiprocessing module. I found that using QProcess to start and manage the GUI was the most reliable way.

    @
    ...
    p=QProcess()
    p.start("python", ["mygui.py"])
    ...
    @

    Hope this helps :o)



  • Thanks for the response! I may end up going the QProcess or subprocess route if I absolutely have to, but I'm currently making use of multiprocessing.Pipe, and I would greatly prefer not having to reimplement those features.



  • I ended up using QLocalServer/Socket in place of pipes, which at least allows the use of the signal/slot mechanism, though I appreciate the reluctance to reimplement things.



  • Ahh, I didn't know about QLocalServer. I had originally looked at using python's socket library, but I didn't think about checking out Qt's. If it transparently handles signal/slots that might be the easiest approach. I'll give it a shot. Thanks!

    Edit: Okay, it looks like it doesn't handle signal/slots in the way I thought you meant. It doesn't transparently send them over the network. There does appear to be a third party library for that (QxtRPCPeer), but it doesn't have python bindings. I guess I'm stuck either going without a child GUI process or reimplementing the functionality provided by multiprocessing.Pipe.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.