Страницы

Поиск по вопросам

воскресенье, 12 января 2020 г.

QProcess - как получить вывод процесса до его завершения?

#qt #qt5


Есть приложение на Qt, включающее код такого вида :

QProcess proc;
...
proc.setProgramm("Python34\\python");
proc.setArguments(QStringList{"hello.py"});
proc.setProcessChannelMode(QProcess::MergedChannels);
connect(&proc, &QProcess::readyReadStandardOutput, []() {
  QString output = QString(proc.readAllStandardOutput());
  ...
});
proc.start();


Но readyReadStandardOutput отлавливается только после завершения процесса. В моём
случае - требуется проделать определённые действия до завершения (по наличию в выводе
определённого текста).

Как это реализовать?

upd. Более подробный код имеет вид :

class Window: public QMainWindow {
...
  private:
    QVector processes;
    void createProcesses();
    void prepareProcess(QProcess* proc);
}

void MainWindow::createProcesses() {
  for(int i=0;...) {
    processes.append(new QProcess());
    prepareProcess(&processes[processes.size()-1]);
  }
}

void MainWindow::prepareProcess(QProcess* proc) {
  proc->setProgramm("Python34\\python");
  proc->setArguments(QStringList{"hello.py"});
  proc->setProcessChannelMode(QProcess::MergedChannels);
  connect(&proc, &QProcess::readyReadStandardOutput, []() {
    QString output = QString(proc->readAllStandardOutput());
    ...
  });
  proc->start();
}


UPD. А в Qt ли вообще дело? Обнаружил следующее.
При запуске, например ping /t ya.ru результат выводится. Но, с применением например,
следующего питоноскрипта - нет

import time
while True:
  print("Hello")
  time.sleep(1)

    


Ответы

Ответ 1



В справке по обозначенному сигналу говорится, что последний будет отправляться по мере поступления новых данных. То есть не по завершению процесса, а именно во время работы процесса. Метод QProcess::start() является асинхронным. Объект QProcess у Вас создаётся в стеке. В связи с этим, возможно, что проблема заключается в несвоевременном уничтожении объекта, либо в отсутствии вызова цикла событий, что в свою очередь ведёт к помещению отправленного сигнала в очередь. Соответственно, и получается, что сигнал доходит постфактум, а не тогда, когда его вызвали. Создавайте объект QProcess в куче (через new), либо после вызова метода QProcess::start() при помощи QEventLoop активируйте локальный цикл событий. Ну или, как ещё один вариант, воспользуйтесь блокирующим ожиданием: QProcess::waitForReadyRead().

Ответ 2



Дело было не в приложении на Qt, а в буферизации вывода python-ом (https://stackoverflow.com/questions/230751/how-to-flush-output-of-python-print) Лечится запуском с опцией -u

Комментариев нет:

Отправить комментарий