Is it possible to make a PyQt5 app that calls a python script via a subprocess fully self-contained?

748 views Asked by At

Apologies if I am missing something obvious here. I have a PyQt5 app that I've frozen using the awesome fbs package. Within the app, a Python script is called via a PyQt subprocess, i.e. like this:

    command = "python LaunchPPTKwin.py"
    self.child = QProcess()
    self.child.start("cmd.exe /C python LaunchPPTKwin.py")
    self.child.waitForFinished(-1)

This works fine when the app is run on the machine on which the app was built. When I bring it to another machine, however, the app runs but the LaunchPPTKwin.py script is never executed. I assume this is because the other machine does not have python installed and/or does not have the LaunchPPTKwin.py script locally. My goal is to create an app so that this will work without the user needing to separately download python or the script, i.e. to make the app totally self contained. Is this possible using fbs?

P.S. Both machines are using Windows 10.

2

There are 2 answers

0
Matt On

Figured it out: I just compiled the Python script being called into an executable using Pyinstaller, and then called that executable. So my subprocess call above turned into:

command = "cmd.exe /C LaunchPPTKwin.exe"
self.child = QProcess()
self.child.start(command)
self.child.waitForFinished(-1)
2
gelonida On

Either python is not installed or python is not in the search path and you had to locate it.

If python were installed, but not in the search path following code should work.

self.child.start("cmd.exe /C start LaunchPPTKwin.py")

If python is not installed at all you could cheat with more effort.

you had to make sure, that your frozen application can handle a command line parameter that allows it to start another script.

It would take the python file. add the base directory of that file to sys.path strip of the .py suffix of the basename and import it and call it's main function. THis works however only if the script had following lines at its end

def main():
    the_code_you_want_to_start
    ...


if __name__ == "__main__":
    main()

It would further only work if all modules, that this file imports are already used by your frozen app.

So you see it's a little complicated, but I did something similiar with a py2exe application and with a pyinstaller application