16

I am writing a GUI program using PyQt4. There is a button in my main window and by clicking this button. I hope to launch a background process which is an instance of a class derived from processing.Process.

class BackgroundTask(processing.Process):
    def __init__(self, input):
        processing.Process.__init__(self)
        ...

    def run(self):
        ...

(Note that I am using the Python2.5 port of the python-multiprocessing obtained from http://code.google.com/p/python-multiprocessing/ that is why it is processing.Process instead of multiprocessing.Process. I guess this should not make a difference. Am I right?)

The code connected to the button click signal is something simply like

 processing.freezeSupport()
 task = BackgroundTask(input)
 task.start()

The program works as expected under the python intepreter, i.e. if it is started from the command line "python myapp.py".

However, after I package the program using py2exe, everytime when I click that button, instead of starting the background task, a copy of the main window pops up. I am not sure what is the reason of this behavior. I guess it is related to the following note addressed at http://docs.python.org/library/multiprocessing.html#multiprocessing-programming

"Functionality within this package requires that the main method be importable by the children. This is covered in Programming guidelines however it is worth pointing out here. This means that some examples, such as the multiprocessing.Pool examples will not work in the interactive interpreter "

The only place I have if name == "main" is in the main module as in a typical pyqt program

if __name__ == "__main__":
    a = QApplication(sys.argv)
    QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()"))
    w = MainWindow()
    w.show()
    a.exec_()

Any solutions on how to fix this problem? Thanks!

Bing Jian
  • 994
  • 3
  • 10
  • 18
  • Can you clarify: have you protected the main module as described in the multiprocessing docs? or don't you have access to the main module (I don't know how pyqt works)? it's also worth checking that you're using the latest version of py2exe. I've had problems in the past that turned out to have been caused by out of date py2app/py2exe – James Jan 15 '10 at 19:07
  • Thank you for the comment. I just added the __name__ == "__main__" part in my post. Not sure if I am protecting the main module or not. The latest version of py2exe I found from http://sourceforge.net/projects/py2exe/files/ was released on 2008-11-16 so I think I am using the latest version of py2exe. – Bing Jian Jan 15 '10 at 19:42

3 Answers3

26

I think your actual problem has to do with this:

The program works as expected under the python intepreter, i.e. if it is started from the command line "python myapp.py".

However, after I package the program using py2exe, every time when I click that button, > instead of starting the background task, a copy of the main window pops up.

You need to add a special call to the freeze_support() function to make the multiprocessing module work with "frozen" executables (eg, those made with py2exe):

if __name__ == "__main__":
    # add freeze support
    processing.freeze_support()
    a = QApplication(sys.argv)
    QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()"))
    w = MainWindow()
    w.show()
    a.exec_()

Reference: http://docs.python.org/library/multiprocessing.html#multiprocessing.freeze_support

Community
  • 1
  • 1
Daniel G
  • 67,224
  • 7
  • 42
  • 42
  • 1
    +1: Ran into the exact same problem some time ago, used the exact same fix. – Torsten Marek Feb 04 '10 at 00:58
  • 1
    Thanks a lot. It works! I was aware of this freeze_support() function but I did not put it in the right place. Instead of putting it before a = QApplication(sys.argv), I put it every time before a new process instance is created, which seems does not work. – Bing Jian Feb 05 '10 at 15:47
0

"Functionality within this package requires that the main method be importable by the children."

I think this means you have to have main() function defined somewhere.

bialix
  • 20,053
  • 8
  • 46
  • 63
0

The question is concerning Python 2 and was solved. For Python 3, it would look like:

from multiprocessing import freeze_support

if __name__ == '__main__':
    freeze_support()

    a = QApplication(sys.argv)
    ...
timetear
  • 167
  • 1
  • 1
  • 8