在Qt中获取输出:' QProcess :: start()'和' QProcess:readAllStandardOutPut()'

时间:2018-04-23 08:40:25

标签: python c++ qt qprocess

平台:Windows10 我使用QProcess::start执行Python文件(在同一个目录中),但是我  无法从readAllStandardOutput函数获得结果。

Python文件代码:

test.py

print “hello,world”

Qt的:

#include <QProcess>
#include <QStringList>
#include <QByteArray>
#include <QDebug>

void fun1(){
    QProcess process;
    process.start("python test.py");
    process.waitForFinished();
    QByteArray a = process.readAllStandardOutput();


    qDebug()<<a;
}

int main(){
    fun1();
}

当我执行 test.py 时,我可以获得输出,但是当我使用readAllStandardOutput时,我无法获得它。它只是一个印刷&#34;&#34;没有数据。

#include <QProcess>
#include <QStringList>
#include <QByteArray>
#include <iostream>
#include <QDebug>

void fun2(){
    QStringList args("F:/test.py");
    QProcess process;
    process.execute(QString("Python.exe"), args);
    QByteArray a = process.readAllStandardOutput();
    process.waitForFinished();
    qDebug()<<a;

}

int main(){
    fun1();
    qDebug<<"--------";
    fun2();
}

fun2函数中,函数execute()可以在Qt终端print "hello,world",但我无法通过readAllStandardOutput函数获得标准输出。 a也打印&#34;&#34;没有数据我不知道为什么?

因为我想使用python模块&#34;请求&#34;直接访问url,所以我希望我的C ++代码可以执行这个python文件。所以,如果你有更好的方法,请告诉我。

3 个答案:

答案 0 :(得分:0)

不幸的是,在Qt中获取流程输出有点麻烦。

以下是我在一个项目中的表现:

QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels);
process.start(processToStart, arguments)

// Get the output
QString output;
if (process.waitForStarted(-1)) {
    while(process.waitForReadyRead(-1)) {
        output += process.readAll();
    }
}
process.waitForFinished();

这可能会引发一些问题:

setProcessChannelMode(QProcess :: MergedChannels)将合并输出通道。各种程序写入不同的输出。有些人使用错误输出进行正常记录,有些人使用&#34;标准&#34;输出,一些两者。最好合并它们。

readAll()读取到目前为止可用的所有内容。

它被放入一个带有 waitForReadyRead(-1)的循环中(-1表示没有超时),它将阻塞,直到有东西可供读取。这是为了确保所有内容都被实际阅读 在进程完成后简单地调用readAll()已证明是非常不可靠的(缓冲区可能已经为空)。

答案 1 :(得分:0)

使用waitForReadyRead()Process API读取数据。 waitForReadyRead()将阻塞,直到新数据可用于在当前读取通道上读取。

void fun1(){
    QProcess process;
    process.start("python test.py");
    process.waitForReadyRead();
    QByteArray a = process.readAllStandardOutput();


    qDebug()<<a;
}

答案 2 :(得分:0)

当使用QProcess::start()时,进程在另一个线程中启动,并以异步方式执行,以避免阻塞应用程序的GUI线程(如果您有GUI)。使用waitForReadyRead()也会阻止应用程序的执行,直到流程结束。

您可以考虑使用Qt的信号/插槽系统在可用时捕获进程的输出,而不会阻塞主线程。

此版本的fun1()需要C ++ 11:

void fun1(){
    // instantiate dynamically to avoid stack unwinding before the process terminates
    QProcess* process = new QProcess(); 
    process->start("python test.py");

    // catch data output
    QObject::connect(process, &QProcess::readyRead, [process] () {
        QByteArray a = process->readAll();
        qDebug() <<  a;
    });

    // delete process instance when done, and get the exit status to handle errors.
    QObject::connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                     [=](int exitCode, QProcess::ExitStatus /*exitStatus*/){
        qDebug()<< "process exited with code " << exitCode;
        process->deleteLater();
    });
}

通过这种方式,您还可以管理执行错误,或者至少让用户知道它。