如何读取 QProcess 输出

Posted

技术标签:

【中文标题】如何读取 QProcess 输出【英文标题】:How to read QProcess output 【发布时间】:2019-05-31 07:48:13 【问题描述】:

在 GUI 应用程序的主线程中,我正在启动另一个 GUI 应用程序的 QProcess,它将使用 fputs() 在标准输出中随时间记录一些消息。问题是一段时间后,使用 QProcess 启动的 GUI 应用程序将冻结,因为它的输出不被父级消耗。我知道这是问题所在,因为如果我使用 QIODevice::NotOpen 或 QIODevice::Unbuffered 参数启动 QProcess,它不会卡住,但永远不会达到输出。 我尝试将子进程的 readyRead、readyReadStandardError、readyReadStandardOutput 信号连接到父进程中的插槽,但由于某些原因,这些信号从未发出。我也在每次写入后刷新标准输出。 我的问题是如何强制QProcess在不关闭的情况下实时发送一些数据?

信号的连接,(T-是QProcess的封装):

process->setWorkingDirectory(workingDir);
process->start(prog, argumentsList);
process->waitForStarted();
T* reciver = new V8QProcess(process);
QObject::connect(process, &QProcess::readyRead, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardError, reciver, &V8QProcess::OnMessageRecieved);
QObject::connect(process, &QProcess::readyReadStandardOutput, reciver, &V8QProcess::OnMessageRecieved);

将登录stdout的子进程的代码:

QByteArray bytes = LogMsg::getDisplayable(logMsg, 0).toUtf8();
fputs(bytes.constData(), stdout);
fflush(stdout);

OnMessageRecieved 的代码:

 if (!p)  // p is the QProcess
    return;

QByteArray output;
output.append(p->readAllStandardError()).append(p->readAll());
QString message = QString::fromStdString(output.toStdString()); 

这种方法在运行 shell 脚本或其他简单程序时有效。

【问题讨论】:

为什么你认为readyRead* 信号没有发出?您是否在调试器中设置了断点?你能显示V8QProcess::OnMessageRecieved的代码吗? 是的,我设置了一个断点。 也许您需要在启动 QProcess 之前连接信号。 仍然没有改善的迹象... 你有没有打电话给p->setReadChannel(...)?尝试在V8QProcess::OnMessageRecieved 中将p->readAll() 更改为p->readAllStandardOutput 【参考方案1】:

我发现问题出在我的案子上: 因为我在std::Thread 中启动QProcess,所以跳过了发生的事件(信号),因为std::Thread 没有QThreadQApplication 那样的事件队列。 我使用的解决方案是: 1. 使用QThread 而不是std::thread 2. 不定时拨打QCoreApplication::proccesEvents()

正确的解决方案是使用QThread::exec() 来创建event loop,但这种方法会阻止GUI 应用程序,所以在我的情况下不好。

【讨论】:

以上是关于如何读取 QProcess 输出的主要内容,如果未能解决你的问题,请参考以下文章

使用 QProcess 时无法读取命令的输出

使用 QProcess 读取标准输出

QProcess -> 在 Linux 上从 sftp 读取标准输出

QProcess中多次写入的输出一一读取

试图从生成的 QProcess 中读取标准输出

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