如何从分离的QProcess中读取stdout/stderr [英] How to read stdout/stderr from detached QProcess

查看:525
本文介绍了如何从分离的QProcess中读取stdout/stderr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Qt的初学者.我需要从桌面应用程序中的按钮调用命令行程序.该程序将下载YouTube视频.我还需要从中读取标准错误.我写了以下代码:

I am a total beginner in Qt. I need to call a command-line program from a button in my desktop app. The program downloads a YouTube video. I also need to read standard error from it. I wrote the following code:

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读取.

However the stderr read does not take place.

另一方面,如果我先使用非分离的p.start(),然后再使用waitForFinished(-1),则可以读取stderr,但GUI会冻结直到下载完成.

On the other hand if I use non-detached p.start() and then waitForFinished(-1) then I can read the stderr, but the GUI freezes until the download completes.

如何解决?

一个相关的问题:我还希望某种方式能够实时读取下载过程的输出,以便可以在GUI中显示它. youtube-dl提供如下进度报告:

A related problem: I would also like some way to be able to read the outputs of the download process in real-time, so that I can display it in the GUI. youtube-dl gives progress reports like this:

[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
...

我希望能够在生成它们时读取它们.

I'd like to be able to read these as and when they are generated.

推荐答案

由于问题的性质,以上所有答案都不正确. @aakashjain要求进行分离过程.你们建议的内容仅在启动过程仍仍处于附着状态的情况下才有效.

All the answers above are incorrect due to the nature of the question. @aakashjain asks for a detached process. What you guys suggest works only in the case the started process is still attached.

QProcess p
p.startDetached(...)

QProcess::startDetached(...)

QProcess :: startDetached()是静态方法,它不属于任何对象,也不返回任何对象.调用此方法并成功后,该过程将不再以任何方式附加到产生它的过程(您的应用程序).

QProcess::startDetached() is a static method and it is NOT part of any object or returns one. Once you call this method and it succeeds the process will no longer be attached in any way to the process that has spawned it (your application).

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

I suggest you look first at the official documentation on this method and then read more about interprocess communication as well how to pipe the output of one process to another (in this case detached process to the terminal).

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

I stumbled upon the issue even of basic controll using QProcess::startDetached() in PyQt4 where I did exaclty what the @DmitrySokolov suggested. For my surprise the state was always zero, nothing could be set or retrieved using the QProcess non-static method. After some digging and asking around it was pointed to me exactly what I've written at the beginning of my answer - if you use QProcess::startDetached(), the control that follows has to be through the system tools (such as the kill command, pipes etc.) because you have no object you can actually work with.

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

QProcess::startDetached() offers two important return values:

  • 方法本身的返回值-一个布尔值,它告诉您启动过程是成功(== true)还是失败(== false)
  • 该函数的qint64 * pid指针参数-如果该进程已成功启动,则 pid 将包含分离的进程的PID(进程标识符)
  • the return value of the method itself - a boolean, which tells you if the starting of the process has succeeded (==true) or failed (==false)
  • the qint64 * pid pointer argument of the function - if the process has been started successfully, the pid will contain the PID (Process Identifier) of the detached process

您可以根据自己的喜好使用此PID与进程进行交互(并且进程本身允许您这样做;))-您可以终止它,通过管道输出其输出,使其进入睡眠状态等.

You can use this PID to interact with the process however you like (and the process itself allows you to of course ;)) - you can terminate it, pipe its output, put it to sleep etc.

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

Now back to your problem. There are three solutions here:

  • 启动子进程-该进程将包含在QProcess对象中,您可以按照@DmitrySokolov的描述与之交互.但是,这将阻塞您的主线程,该主线程将处理UI,直到子进程完成其任务并停止(主线程在您的Qt应用程序的进程内运行).我怀疑您是否希望冻结UI(正如您通过自己进行实验所注意到的那样),尤其是因为我们正在谈论下载可能较大量的视频数据...
  • 开始一个独立的过程-在此解决方案列表之前我已经描述过.但是,它需要对进程间通信有更多的了解.如果您愿意接受,并且想花一些时间在这个主题上工作(我只能鼓励您这样做!),请这样做
  • 在其中启动线程和子进程-不仅您可以对下载任务进行真正的整洁控制,而且还可以通过插槽和向UI发出信号来提供出色的反馈,这将改善用户体验很多.这是用于此类任务的最广泛使用的方式,我还可以在您的注释中看到要在ui->descBox中输出进度(您还可以添加QProgressbar以使输出更加用户友好并执行stdout/stderr东西在后台仅供您查看).我还没有测试过这个结果,但是应该可以.
  • Start a child process - the process will be contained in a QProcess object, which you can interact with as @DmitrySokolov has described. However this will block you main thread, which handles the UI until the child process has finished its task and has stopped (main thread runs inside the process of your Qt app). I doubt you want your UI to freeze (as you have noticed by experimenting on your own) especially since we are talking about downloading possibly large contents of video data...
  • Start a detached process - what I've described before this list of solutions. It requires however a more in debt understanding of interprocess communication. If you are up for it and want to spend some time working on this topic (I can only encourage you to do that!), do it
  • Start a thread and a child process in it - not only you will have a really neat control over the download task but you will also be able to give great feedback via slots and signals to the UI, which will improve the user experience a lot. This is the most widely used way for such task and I can also see in your comment that you want to output the progress in ui->descBox (you can also add a QProgressbar to make the output more user-friendly and do the stdout/stderr thing in the background just for you to see). I haven't tested this to be honest but it should work.

这篇关于如何从分离的QProcess中读取stdout/stderr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆