0

I'm having this issue executing a python3 script from QProcess. The python script is printing the time from second to second and it is working fine from command line. In Qt, the signal readyReadStandardOutput() is connected to a slot where readAllStandardOutput() is called to read the standard output from the script. The problem is that the slot is called only once! It prints the time once and then no more. The state of QProcess remains in "running" state. readyReadStandardError() and error(QProcess::ProcessError) signals are never called.

Why is the slot called only once when it has to be called every second? Thanks

Python script:

import time, threading
def foo():
    print(time.ctime())
    threading.Timer(1, foo).start()

foo()

Qt:

MClass::MClass(QObject* parent)
{
    m_process = new QProcess(this);
    connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(onTest()));
    connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(onTestErr()));
    connect(m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(onTestErr()));
    connect(m_process, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(onTestState()));

    startProcess();
}

void MClass::startProcess()
{
        QString script= "../../python/test.py";

        QString pythonCommand = "python3 " + script;

        printf("PyCommand: %s\n", pythonCommand.toStdString().c_str());
        m_process->start(pythonCommand);

//        m_process->start("python3", QStringList()<<script);
    }
}

void MClass::onTest()
{
    qDebug()<<"------------------ON TEST";
    while(m_process->canReadLine())
    {
        qDebug()<<m_process->readAllStandardOutput();
    }
}

void MClass::onTestErr()
{
    qDebug()<<"------------------ON ERR: " << m_process->errorString();
}

void MClass::onTestState()
{
    qDebug()<<"------------------ STATE CHANGED: " << m_process->state();
}
10
  • Can we see your python script? Is it an interactive script, i.e do you read from standard input? It may explains why the process stays running. Commented Apr 20, 2018 at 8:26
  • @jbh the python script is above the qt code Commented Apr 20, 2018 at 8:27
  • @IspasClaudiu What if you just call the readAllStandardOutput, whitout the while loop and without testing the canReadLine() ? Commented Apr 20, 2018 at 8:28
  • 1
    @S.Monteleone it doesn't make any difference Commented Apr 20, 2018 at 8:29
  • 2
    It seems to me that the cause of this behavior is that only the first print is executed in the main thread, and the others in the other threads. Commented Apr 20, 2018 at 8:31

1 Answer 1

2

I think the problem lies in python handling of standard output. I tried this script:

def foo():
    #print(time.ctime())
    sys.stdout.write(time.ctime()) 
    sys.stdout.write("\n")
    sys.stdout.flush()
    threading.Timer(1, foo).start()

where I substituted print with sys.stdout.write and it worked. I think what's really doing the difference is the call to flush.

In other words, your script runs forever, so the standard output never gets flushed. If you try this other script, which ends after five iterations:

def bar():    
    x = 0      
    while x < 5:
        print(time.ctime())
        time.sleep(1)
        x = x + 1

in the Qt app you'll see the whole output after five seconds.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, it was a flushing problem. Your code works however also printing with the flash flag on true does the job: print("msg: ", end='\n', file=sys.stdout, flush=True)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.