在 Qt 中获取输出:'QProcess::start()' 和 'QProcess:readAllStandardOutPut()'
Posted
技术标签:
【中文标题】在 Qt 中获取输出:\'QProcess::start()\' 和 \'QProcess:readAllStandardOutPut()\'【英文标题】:Get Output in Qt: 'QProcess::start()' and 'QProcess:readAllStandardOutPut()'在 Qt 中获取输出:'QProcess::start()' 和 'QProcess:readAllStandardOutPut()' 【发布时间】:2018-04-23 08:40:25 【问题描述】:平台: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
时我无法得到它。它只是打印没有数据的“”。
#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
函数得到标准输出。不知道为什么还打印“”没有数据?
因为我想使用python模块“请求”直接访问一个url,所以我希望我的C++代码可以执行这个python文件。所以,如果你有更好的方法,请告诉我。
【问题讨论】:
【参考方案1】:当使用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();
// 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();
);
// start the process after making signal/slots connections
process->start("python test.py");
通过这种方式,您还可以管理执行错误,或者至少让用户意识到这一点。
【讨论】:
非常感谢,你的回答很详细,我找到了一个很好的解决方案来完成我的工作。 @Gabriella Giordano ,我认为QObject::connect
应该放在process->start()
之前
@MohammadKanan 是的,你是对的。刚刚编辑。谢谢:)【参考方案2】:
不幸的是,在 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) 将合并输出通道。各种程序写入不同的输出。有些使用错误输出进行正常日志记录,有些使用“标准”输出,有些则两者兼而有之。最好合并它们。
readAll() 读取目前可用的所有内容。
它被放入一个带有 waitForReadyRead(-1) 的循环中(-1 表示没有超时),这将阻塞直到有内容可供读取。这是为了确保所有内容都被实际读取。 在进程完成后简单地调用 readAll() 被证明是非常不可靠的(缓冲区可能已经是空的)。
【讨论】:
谢谢,我知道为什么我不能得到应该使用 waitForReadyRead() 函数的结果。【参考方案3】:使用 waitForReadyRead() Process API 读取数据。 waitForReadyRead() 阻塞,直到当前读取通道上有新数据可供读取。
void fun1()
QProcess process;
process.start("python test.py");
process.waitForReadyRead();
QByteArray a = process.readAllStandardOutput();
qDebug()<<a;
【讨论】:
以上是关于在 Qt 中获取输出:'QProcess::start()' 和 'QProcess:readAllStandardOutPut()'的主要内容,如果未能解决你的问题,请参考以下文章