gihidoma gihidoma - 10 months ago 48
Python Question

Qt C++ - How to successfully pass data to child process?

I wrote a short piece of test software, whose goal is to actually start my python virtual environment via a childprocess and execute some commands in that process. It seems the child process never receives the data.

The code bellow does 2 things: pass data, ie the string "John" to the child process and reading the log file every time the string is passed (to check whether eg the command was properly understood).

In my terminal I type this (I intentionally execute an incorrect command for testing purposes):

$ script -f -c python2 python.log
Script started, file is python.log
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> John
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'John' is not defined


and my python.log file now contains (as expected and wanted):

Script started on Don 17 Aug 2017 01:04:54 CEST
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> John
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'John' is not defined
>>>


the corresponding code which is supposed to replicate this behaviour:

when pushing a button on my gui this code gets executed:

void MainWindow::mainFunction()
{
QFile myfile("/home/John/Desktop/python.log");
QTextStream input(&myfile);
if(!myfile.open(QIODevice::ReadOnly)) {
QMessageBox::information(0, "error", myfile.errorString());
}

QProcess p; //childprocess
QStringList params;
qint64 successFailWrite;
qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
connect(&p, &QProcess::errorOccurred, qApp, &QApplication::aboutQt );
//connect(&p, &QProcess::started, qApp, &QApplication::aboutQt);
params<<"-f"<<"-c"<<"python2 python.log";
qDebug()<<"parameters: "<<params;
p.start("script", params);
while(!p.waitForStarted())
{qDebug()<<"waiting for started";}


while(1)
{
successFailWrite = p.write("John", 1);

while(!input.atEnd())
{
QString line = input.readLine();
qDebug()<<"read: "<<line;
}
}
}


When executing this code, my python.log file is always empty yet the successFailWrite variable is 1, which means it siccessfully wrote the string to the process. What is also strange is that when I replace

p.start("script", params);


with: p.start("scriptttt", params);

nothing changes at all, the aboutQt SLOT doesn't get activated and I can't see any error message anywhere.
According to the Qt documents I should be able to interface with my process using write() just like an IODevice

What am I doing incorrectly?

EDIT: params<<"-f"<<"-c"<<"python2"<<"python.log"; doesn't work neither.

I can however see that this happens when my code is being executed:

$ ps aux | grep python

John+ 7436 0.0 0.0 22352 2716 ? S 11:56 0:00 script -f -c python2 python.log
John+ 7437 0.5 0.1 31648 6924 pts/20 Ss+ 11:56 0:00 python2
John+ 7439 0.0 0.0 14540 1020 pts/0 S+ 11:56 0:00 grep --color=auto python

Answer Source

Your code has a couple of problems. Firstly, as pointed out in the comments, the following code...

p.write("John", 1);

will only write a single character. Since you have a null terminated string simply use the QIODevice::write overload that accepts that and remember to include a newline character...

p.write("John\n");

More importantly though, you have...

params << "-f" << "-c" << "python2 python.log";

You need to split "python2 python.log" -- that's two separate arguments. Try...

params << "-f" << "-c" << "python2" << "python.log";

With the above changes the code works fine for me.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download