我是 Qt 的初学者。我需要通过桌面应用程序中的按钮调用命令行程序。该程序下载 YouTube 视频。我还需要从中读取标准错误。我写了下面的代码:
void YoutubeDL::on_downloadButton_clicked()
{
[...]
QProcess p;
p.startDetached("youtube-dl -f " + get + " " + ui->urlBox->text());
QString perr = p.readAllStandardError();
if (perr.length())
ui->descBox->setText("Error during download.\n" + perr);
else
ui->descBox->setText("Download completed!");
}
但是不会发生 stderr 读取。
另一方面,如果我使用非分离的 p.start()
然后使用 waitForFinished(-1)
那么我可以读取 stderr,但是 GUI 卡住直到下载完成。
如何解决这个问题?
一个相关问题:我还想要一些能够实时读取下载过程输出的方法,以便我可以在 GUI 中显示它。 youtube-dl 给出这样的进度报告:
[download] 0.0% of 2.00MiB at 173.22KiB/s ETA 00:12
[download] 0.1% of 2.00MiB at 105.01KiB/s ETA 00:19
[download] 0.3% of 2.00MiB at 96.86KiB/s ETA 00:21
[download] 0.7% of 2.00MiB at 105.23KiB/s ETA 00:19
[download] 1.5% of 2.00MiB at 100.29KiB/s ETA 00:20
...
我希望能够在它们生成时阅读它们。
最佳答案
由于问题的性质,以上所有答案都不正确。 @aakashjain 要求一个分离 过程。你们的建议仅在启动过程仍然附加的情况下才有效。
QProcess p
p.startDetached(...)
与
相同QProcess::startDetached(...)
QProcess::startDetached() 是一个静态方法,它不是任何对象的一部分或返回一个对象。一旦您调用此方法并成功,该进程将不再以任何方式附加到生成它的进程(您的应用程序)。
我建议你先看看 official documentation on this method然后阅读更多关于 interprocess communication 的信息以及如何将一个进程的输出通过管道传输到另一个进程(在本例中是分离进程到终端)。
我什至在 PyQt4 中使用 QProcess::startDetached() 时偶然发现了基本控制的问题,在那里我完全按照@DmitrySokolov 的建议做了。令我惊讶的是,状态始终为零,无法使用 QProcess 非静态方法设置或检索任何内容。经过一番挖掘和询问后,我得到的正是我在回答开头所写的内容——如果您使用 QProcess::startDetached(),则必须通过系统工具(例如 kill 命令、管道等),因为您没有实际可以使用的对象。
QProcess::startDetached() 提供了两个重要的返回值:
- 方法本身的返回值 - 一个 bool 值,它告诉您进程启动是成功 (==true) 还是失败 (==false)
- 函数的 qint64 * pid 指针参数 - 如果进程已成功启动,pid 将包含分离进程的 PID(进程标识符)
您可以使用此 PID 以您喜欢的任何方式与进程交互(进程本身当然允许您这样做;))- 您可以终止它、通过管道传输其输出、使其休眠等。
现在回到你的问题。这里有三种解决方案:
- 启动子进程 - 该进程将包含在 QProcess 对象中,您可以按照@DmitrySokolov 的描述与其进行交互。然而,这将阻止您处理 UI 的主线程,直到子进程完成其任务并停止(主线程在您的 Qt 应用程序的进程内运行)。我怀疑您希望您的 UI 卡住(正如您通过自己的实验注意到的那样),尤其是因为我们正在谈论下载可能包含大量视频数据的内容...
- 开始一个分离的过程——我在这个解决方案列表之前已经描述过的。然而,它需要对进程间通信有更多的了解。如果您愿意并想花一些时间研究这个主题(我只能鼓励您这样做!),那就去做吧
- 在其中启动一个线程和一个子进程 - 您不仅可以真正巧妙地控制下载任务,还可以通过插槽和信号向 UI 提供很好的反馈,这将改善用户体验很多。这是此类任务使用最广泛的方法,我还可以在您的评论中看到您想在
ui->descBox
中输出进度(您还可以添加 QProgressbar 以使输出更用户化-友好并在后台执行 stdout/stderr 操作,仅供您查看)。老实说,我还没有对此进行测试,但它应该有效。
关于c++ - 如何从分离的 QProcess 中读取标准输出/标准错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22574867/