在 Qt 中启动单独的进程

Posted

技术标签:

【中文标题】在 Qt 中启动单独的进程【英文标题】:Launch separate process in Qt 【发布时间】:2018-04-18 14:37:54 【问题描述】:

我正在尝试从 Qt 应用程序运行 python 文件,但是我有两个问题。一是它似乎没有启动 python 工具。其次,当我尝试仅使用记事本作为示例进行简单测试时,我注意到当我关闭我的应用程序时记事本也会关闭。我不确定为什么 python 工具没有启动,以及为什么进程不是真正独立于 Qt 应用程序。

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");

更新 #1:第二次尝试仍然失败...... 我进行了更多研究,甚至尝试了下面的代码,现在它给了我错误:

ImportError: 没有名为站点的模块

这让我很困惑,因为我正在设置环境路径。归根结底,我想做的就是运行如下的 shell 命令,但来自 Qt。

"C:/python27/python.exe" "C:/Users/john/testing.py"

最新代码:

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);

【问题讨论】:

startDetached 返回 false 以防出错。你检查返回值了吗? 奇怪的是这行得通:QProcess::startDetached("notepad.exe", QStringList() 您应该提供 QProcess 的规范路径,该路径使用正在运行的操作系统的语法。换句话说,您是否尝试过键入 QProcess::startDetached(C:\\python27\\python.exe") ? @S.Monteleone 我用最新发现更新了问题。 很明显,问题在于路径字符串使用了错误的斜杠。现在,关于 python 的抱怨,python 脚本现在位于不同的位置有什么原因吗?是同一个脚本吗? 【参考方案1】:

我将回顾各种 cmet 中列出的详细信息,并为您的问题提供最终解决方案。

路径和反斜杠

QProcess API 在 Win32 平台上使用 CreateProcess,因此必须按照操作系统约定提供路径(使用反斜杠而不是斜杠)。在您的示例中,“C:/python27/python.exe”必须转换为“C:\Python27\python.exe”。这里的双反斜杠是由于 C++ 字符串文字转义造成的。

环境

正如您在更新中正确指出的那样,您需要设置一些环境变量才能使 Python 解释器按预期工作。

您还指定要分离调用的 python 脚本,这样即使您的应用程序关闭,它也可以运行。

这在 Qt 在 Qt 5.10 中引入(参见 Qt 博客中的 this 帖子)。

对于 Qt 5.10,正确的代码是:

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();

您在更新答案中的代码不起作用,因为它使用了 static execute() 方法。您会看到,静态方法是类的一部分,这意味着您可以从该类的对象实例中调用它,但是,由于它是静态的,因此无法访问对象的成员。也就是说,execute() 无法知道你之前设置的 QProcessEnvironment。

出于同样的原因,调用接受两个参数的 startDetached() 重载也不起作用,因为它也是静态的。

Qt 博客文章准确解释了为什么会创建这种新的非静态重载,并且非常适合您的场景。

关闭我的应用程序会杀死 python 解释器。

如果您在 debug 中运行您的 Qt 应用程序,这是正确的。这是因为分离的进程(在本例中为 python 解释器)也附加到调试器,并且由于在关闭 Qt 应用程序时关闭了调试会话,这也会杀死 python。

但是,如果您运行已部署的应用程序(双击 exe,而不是从调试器中),它应该可以按预期工作。

【讨论】:

以上是关于在 Qt 中启动单独的进程的主要内容,如果未能解决你的问题,请参考以下文章

在 Qt 中隐藏和重新启动相同的 QApplication 实例

Qt 进程和线程之二:启动线程

Qt通过QProcess启动进程并传递命令行参数

Qt通过QProcess启动进程并传递命令行参数

qt中进程的使用

QT软件开发: QProcess启动进程完成交互并获取输出