Reputation: 6147
I'm attempting to run an python file from a Qt application however I have two problems. One it does not appear to launch the python tool. And secondly when I try doing a simple test using just notepad as an example, i notice that Notepad closes when i close my application. I'm not sure why the python tool is not launching and why the process is not truly independent from the Qt application.
else if(QFileInfo(path).isFile() && path.endsWith(".py", Qt::CaseInsensitive))
{
QProcess::startDetached("C:/python27/python.exe", QStringList() << "C:/Users/john/testing.py");
QProcess *proc = new QProcess();
proc->startDetached("notepad.exe");
}
Update #1: Second attempt still failing.... I've research a bit more and even attempted the code below and it's now giving me the error:
ImportError: No module named site
Which is confusing to me because I'm setting the env paths. At the end of the day all im trying to do is run a shell command like the following, but from Qt.
"C:/python27/python.exe" "C:/Users/john/testing.py"
Latest code:
QString program( "C:\\Python27\\python.exe" );
QStringList args = QStringList() << "C:\\Users\\jmartini\\Desktop\\Trash\\testing.py";
QProcess process;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("PYTHONHOME", "C:\\Python27");
env.insert("PYTHONPATH", "C:\\Python27\\Lib");
process.setProcessEnvironment(env);
process.execute(program, args);
Upvotes: 0
Views: 756
Reputation: 2886
I will recap the details enlisted in the various comments and provide the final solution for your question.
Paths and backslashes
The QProcess API uses the CreateProcess on Win32 platforms and therefore paths must be provided in accordance with the OS convention (using backslashes instead of slashes). In your example, "C:/python27/python.exe" must be converted to "C:\Python27\python.exe". The double backslash here is due to C++ string literals escaping.
Environment
As you have correctly noted in your update, you need to set a few environment variables in order to make the Python interpreter work as expected.
You also specified you want to detach the invoked python script, so it can run even when your application is closed.
This is trickier with Qt < 5.10 as the appropriate API to accomplish this task was introduced with Qt 5.10 (see this post from the Qt blog).
With Qt 5.10, the correct code is:
QProcess process;
// set the environment variables
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("PYTHONHOME", "C:\\Python27");
env.insert("PYTHONPATH", "C:\\Python27\\Lib");
process.setProcessEnvironment(env);
// set program name and args
process.setProgram("C:\\Python27\\python.exe");
process.setArguments(args);
// start the detached process
process.startDetached();
The code you have in your updated answer doesn't work because it is using the static execute() method. You see, a static method is part of a class, and this means you can call it from an object instance of that class, however, since it's static, it can't access the object's members. In other words, execute() can't know anything about the QProcessEnvironment you set before.
For the same reason, calling the startDetached() overload which accepts two arguments won't work either, because it is static too.
The Qt blog post explains exactly why this new non static overload was created, and this fits perfectly in your scenario.
Closing my app kills the python interpreter.
This is true if you run your Qt app in debug. That's because the detached process (the python interpreter in this case) is attached to the debugger too, and since the debugging session is closed when your Qt app is closed, this kills python too.
However, if you run your deployed app (double click on the exe, not from the debugger) it should work as expected.
Upvotes: 2