QIODevice::read (QProcess): device not open



  • Hello guys !

    I'm working on QtCreator and I want to use a python script with a xml file from QT Windows.

    The file is open, but I can't use the script :

    QString p_stdout = _process.readAll();
    

    show me : QIODevice::read (QProcess): device not open

    Here is my code :

    // EXEC PYTHON SCRIPT
    
    
        QStringList args = (QStringList() << script_path << employesDesires << file_path) ; // parameters
        QString program = "Python";                                                         // program
    
    
        int exitCode = _process.execute( program, args );
    
        _process.waitForFinished(-1);
    
    //      _process.open(QIODevice::OpenMode()) ;
    
        QString p_stdout = _process.readAll();
    
        QString s = QString::number(exitCode);
    
        ui->labelResult->setText(s);
    

    exitCode return 0

    I searched on many forums but can't find a solution that I can understand..Someone have an idea ?



  • @FoxBandyKoot
    http://doc.qt.io/qt-5/qprocess.html#execute is static. It is supposed to be invoked via QProcess::execute(). You do not even show your declaration of _process, but assuming it's a QProcess instance you cannot use it to access anything from the static call.

    You need to use the member function http://doc.qt.io/qt-5/qprocess.html#start on your QProcess instance.



  • Okey I don't know static notion, but I will try start() function.

    QProcess _process;
    

    Yes it is a Qprocess instance ! :)

    Thanks you for help me !



  • So I tried many things since the last time...
    I do not have the error anymore, but I can not recover the data from my python scrypt which processes an excel file.

    That's where I am, I do not understand how to use signals despite the documentation...

    .h file simplified

    namespace Ui {
        class TabtStatEmp_CountWorkTogether;
    }
    
    class TabtStatEmp_CountWorkTogether : public QDialog
    {
        Q_OBJECT
    
    public:
        // constructor
        explicit TabtStatEmp_CountWorkTogether(QString file_path, QString script_path, QString employesDesires, QWidget *parent = nullptr);
    
        //functions
        QString OpenFile();
    
        QProcess::ProcessChannel StandardOutput;
    
        void setReadChannel(QProcess::ProcessChannel StandardOutput);
    
    
    private:
        
        Ui::TabtStatEmp_CountWorkTogether *ui;
    
        QProcess _process;
    
    };
    

    My .cpp simplified :

    TabtStatEmp_CountWorkTogether::TabtStatEmp_CountWorkTogether(QString file_path, QString script_path, QString employesDesires, QWidget *parent) :
        QDialog(parent),
        ui(new Ui::TabtStatEmp_CountWorkTogether)
    {
    
        ui->setupUi(this);
    
    // OPEN XLS FILE
    
        QFile xslFile(file_path);
        QString test   ;
        xslFile.open(QIODevice::ReadOnly | QIODevice::Text);
    
    
    // EXEC PYTHON SCRIPT
    
    
        QStringList args = (QStringList() << script_path << employesDesires << file_path) ; // parameters
    //    QStringList args = (QStringList() << employesDesires ) ; // parameters
    
        QString program = "Python";                                                         // program
    
    
    
        _process.start(program, args );
    
    //   _process.readAllStandardOutput();
    
        _process.setReadChannel(StandardOutput);
    
    
        QString p_stdout = _process.readAllStandardOutput(); // get output
    
    
        ui->labelResult->setText(p_stdout); // display output
    }
    

    It is a simplified version where the python script know already path of xml file.

    And the python script return :

    # version with 1 parameter
    def __main__(employesChoisis):
        total = Tabstats(employesChoisis)
        str(total)
        
        return total

  • Lifetime Qt Champion

    Hi,

    That's because you're not waiting for your process to finish. See the Synchronous Process API part of QProcess's documentation.



  • So I used your link to place signals. Program start but now I have this error in debbuging mode :

    0_1538904437068_Capture.PNG

    This my code :

    // OPEN XLS FILE
    
        QFile xslFile(file_path);
        xslFile.open(QIODevice::ReadOnly | QIODevice::Text);
    
    
    // EXEC PYTHON SCRIPT
    
    
       // QStringList args = (QStringList() << script_path << employesDesires << file_path) ; // parameters
        QStringList args = (QStringList() << script_path << employesDesires ) ; // parameters
    
        QString program = "Python";                                                         // program
    
        QByteArray p_stdout;
    
        _process.start(program, args );                                 // START PROG
    
        if (_process.waitForStarted()){                                 // Check if python is running
    
            QMessageBox::warning(this,tr("A COMMENCE"), tr("A COMMENCE"));
    
            _process.setReadChannel(StandardOutput);                    // OPEN CHANNEL FOR READ
    
    
            p_stdout = _process.readAllStandardOutput();                // get output
    
        }
    
        _process.closeReadChannel(StandardOutput);                      // Stop read
    
        QMessageBox::warning(this,tr("A FINIT"), tr("A FINIT"));
    
    //    QString AA = QString::QByteArray(p_stdout[0]); // Doesn't exist
    
         ui->labelResult->setText(p_stdout); // display output
    
        if (!_process.waitForFinished()){                               // If process crash, stop it
            return;
        }
    

    This error happens when the following instruction is running :

    p_stdout = _process.readAllStandardOutput();                // get output
    

  • Lifetime Qt Champion

    Can you run your application through the debugger to get more details about what is happening ?



  • I'm not sure about what you wanna see, so I take so captures :
    BREAK POINT 1
    0_1539111993709_BP1.PNG

    BREAK POINT 2
    0_1539111996219_BP2.PNG

    AFTER BREAK POINT 2
    0_1539112035030_BP3.PNG


  • Lifetime Qt Champion

    What does the script you launch do ?



  • It makes a count of how many times employes choosed have worked together, based on a xlsx file. Finally return this number (that I cast to string before)

    Sorry for faults, I'm not english :/ And thanks you really for taking time to help me ^^

    # version with 1 parameter
    def __main__(employesChoisis):
        total = Tabstats(employesChoisis)
        str(total)
        
        return total
    


  • @FoxBandyKoot

    Finally return this number (that I cast to string before)

    This may not be relevant to whatever your problem is, but:

        total = Tabstats(employesChoisis)
        str(total)
        
        return total
    

    This does not "cast the string before returning as a result". Python str() is a function returning a string. It does not change its argument. Your standalone str(total) line has no side-effects. Your function returns whatever type is returned from Tabstats(). If you need to force-convert return result to a string: return str(total).


  • Lifetime Qt Champion

    Do you have the same problem if you run a dummy python application ?



  • @JonB

    Okay so I changed it, thanks you !

    @SGaist
    I created a test.py just for test :

    def __main__(employesChoisis):
        
        
        return "TEST"
    

    Same error :/


  • Lifetime Qt Champion

    And if you just start a normal command line tool like dir ?



  • @FoxBandyKoot
    The problem is what I see in the debugger output window is happening while you try to run/debug your program, right? You could put messages in/tell us where exactly you receive the warnings as you step through the code....

    Right, I am now peering at the screenshot code you are using.

    1. Remove/comment out
     _process.setReadChannel(StandardOutput);                    // OPEN CHANNEL FOR READ
        _process.closeReadChannel(StandardOutput);                      // Stop read
    
    

    I am hoping that will get rid of the nasty output?

    1. Your parent program is intended to read whatever the sub-process sends to its stdout. Yours is sending nothing. You cannot "return a string" like "TEST" from any program, Python or otherwise (you can only return an integer). Your test.py should probably be going print("HELLO") (Python 3), for what you want.


  • @SGaist
    I tried to launch "dir" but nothing is happening

    0_1539443911364_fea54747-28f1-4369-b3c2-08181888146f-image.png

    @JonB
    Yes that's it, when I debug I can see this error, on instruction readAllStandardOutput();
    And the application crash...

    0_1539444144651_d52f806f-9b41-4599-9778-c39cd31d1d50-image.png

    If I'm not in debug mode, program continues... that's really weird
    And when this instruction happens :

    ui->labelResult->setText(p_stdout); // display output
    

    Nothing appears. I don't understand why I should comment out functions which open and close channels... My true script return henceforth a integer :
    0_1539444768297_95e358f5-0c6d-4a96-9e72-797e5d36f199-image.png

    You want me to show you the code that precedes the script?



  • @FoxBandyKoot

    I tried to launch "dir" but nothing is happening

    How do you know "nothing is happening" from such a command? Since you're not collecting the output, what do you expect to see?

    I don't understand why I should comment out functions which open and close channels...

    Because I don't think you want them, and I don't think it should be done that way, period. I've never used it and had no problems. Why not try?

    1. _process.readAllStandardOutput()

    this function returns all data available from the standard output of the process

    Since you have only done _process.waitForStarted(), how do you know there is any output yet available to read?



    1. I thinked that I could see content of directory where the script is located in the pyzo interpreter :
      0_1539508130846_b43f7eff-f3df-4434-9cbf-99218a6986fc-image.png

    2. So I tried to comment out these functions :

            _process.setReadChannel(StandardOutput);                    // OPEN CHANNEL FOR READ
    
            _process.closeReadChannel(StandardOutput);                      // Stop read
    

    And the application doesn't crash anymore either in debug mode or not ! But the return value in "p_stdout" is null.

    1. how do you know there is any output yet available to read?

    In my new code I try to implement

    waitForReadyRead and waitForBytesWritten but I don't pass into these functions, I don't know why :/

    Only waitForStarted return true, so the first readAllStandardOutput happens but return nothing from true script or test script.

    #include "ui_tabtstatemp_countworktogether.h"
    
    #include <QMessageBox>
    #include <QDebug>
    
    TabtStatEmp_CountWorkTogether::TabtStatEmp_CountWorkTogether(QString file_path, QString script_path, QString employesDesires, QWidget *parent) :
        QDialog(parent),
        ui(new Ui::TabtStatEmp_CountWorkTogether)
    
    {
    
        ui->setupUi(this);
    
    // OPEN XLS FILE
        
        QFile xslFile(file_path);
        xslFile.open(QIODevice::ReadOnly | QIODevice::Text);
    
    
    // EXEC PYTHON SCRIPT
    
    
       // QStringList args = (QStringList() << script_path << employesDesires << file_path) ; // parameters on final version
    //    QStringList args = (QStringList() << script_path << employesDesires ) ; // second try with just one parameter
        QStringList args = (QStringList() << script_path << employesDesires ) ; // first try without parameter
    
        QString program = "Python";                                                         // program
    
        QString p_stdout;
    
        _process.start(program, args );                                 // START PROG
    
        if (_process.waitForStarted()){                                 // Check if python is running
    
            QMessageBox::warning(this,tr("Have started"), tr("Have started"));
    
    //        _process.setReadChannel(StandardOutput);                    // OPEN CHANNEL FOR READ
    
            p_stdout = _process.readAllStandardOutput();                // get output
    
            if (_process.waitForReadyRead(10000)){                                 // 10 sec to check if data is ready
                QMessageBox::warning(this,tr("Data ready"), tr("Data ready"));
    
                p_stdout = _process.readAllStandardOutput();                // get output
    
    
                if (_process.waitForBytesWritten(10000)){     // 10 sec to check if data is written
                    QMessageBox::warning(this,tr("Data written"), tr("Data written"));
    
                }
            }
    
    
        }
    
    //    _process.closeReadChannel(StandardOutput);                      // CLOSE CHANNEL FOR READ
    
        QMessageBox::warning(this,tr("Have ended"), tr("Have ended"));
    
        ui->labelResult->setText(p_stdout); // display output
    
        if (!_process.waitForFinished()){                               // If process crash, stop it
            return;
        }
    }
    
    
    
    
    // DESTRUCTOR
    TabtStatEmp_CountWorkTogether::~TabtStatEmp_CountWorkTogether()
    {
        delete ui;
    }
    


  • **My first problem has been resolved, so I will close this, and open a topic for my new problem.

    For future people who come to this topic : The solution for "Device not open" was to use "start function" instead of "execute function".

    Thank you people for helping me.**


 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.