如何从分离的QProcess中读取stdout/stderr

Aak*_*ain 3 c++ qt multithreading

我是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!");
}
Run Code Online (Sandbox Code Playgroud)

然而,stderr读取不会发生.

在另一方面,如果我使用非分离p.start(),然后waitForFinished(-1)再我可以读取标准错误,但是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
...
Run Code Online (Sandbox Code Playgroud)

我希望能够在生成它们时阅读这些内容.

rba*_*dar 6

由于问题的性质,上述所有答案都是不正确的.@aakashjain要求一个独立的过程.你们建议的仅适用于启动过程仍然附加的情况.

QProcess p
p.startDetached(...)
Run Code Online (Sandbox Code Playgroud)

是相同的

QProcess::startDetached(...)
Run Code Online (Sandbox Code Playgroud)

QProcess :: startDetached()是一个静态方法,它不是任何对象的一部分或返回一个.一旦调用此方法并且成功,该过程将不再以任何方式附加到生成它的过程(您的应用程序).

我建议你先看看这个方法官方文档,然后阅读有关进程间通信的更多信息,以及如何将一个进程的输出传递给另一个进程(在这种情况下是对终端的分离进程).

我偶然发现了在PyQt4中使用QProcess :: startDetached()的基本控件的问题,其中我做了@DmitrySokolov建议的exaclty.令我惊讶的是,状态始终为零,使用QProcess非静态方法无法设置或检索任何内容.在进行了一些挖掘和询问后,我确切地指出了我在答案开始时所写的内容 - 如果使用QProcess :: startDetached(),则后面的控件必须通过系统工具(例如kill)命令,管道等)因为你没有对象可以实际使用.

QProcess :: startDetached()提供两个重要的返回值:

  • 方法本身的返回值 - 一个布尔值,它告诉您进程的启动是否成功(== true)或失败(== false)
  • 函数的qint64*pid指针参数 - 如果进程已成功启动,则pid将包含已分离进程的PID(进程标识符)

您可以使用此PID与您喜欢的过程进行交互(当然,过程本身允许您使用)) - 您可以终止它,管道输出,让它进入睡眠状态等.

现在回到你的问题.这里有三种解决方案:

  • 启动子进程 - 该进程将包含在QProcess对象中,您可以像@DmitrySokolov所描述的那样与之交互.但是这会阻止你的主线程,它处理UI直到子进程完成它的任务并且已经停止(主线程在你的Qt应用程序的进程内运行).我怀疑你是否希望你的用户界面冻结(正如你通过自己试验所注意到的那样),特别是因为我们正在谈论下载可能大量的视频数据...
  • 启动一个独立的过程 - 我在此解决方案列表之前所描述的内容.然而,它需要更多的债务理解进程间通信.如果你愿意并希望花一些时间研究这个话题(我只能鼓励你这样做!),做吧
  • 在其中启动一个线程和一个子进程 - 不仅您将对下载任务有一个非常巧妙的控制,而且您还可以通过插槽和信号向UI提供很好的反馈,这将大大改善用户体验.这是这种任务使用最广泛的方式,我也可以在你的评论中看到你想输出进度ui->descBox(你也可以添加一个QProgressbar来使输出更加用户友好,并在stdout/stderr中做东西)背景只为你看).我没有测试过这是诚实的,但它应该工作.