Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

PyQt script under C++ Qt doesn't work under Windows.



  • I'm trying to run a Python (PyQt) script under a Qt C++ applciation. This script works fine from console (linux) and cmd (windows 10).

    This is the script:

    plugin_loader.py

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import imp
    import os
    import sys
    import operator
    from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
    from DialogoImprimir import DialogoImprimir
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        myapp = DialogoImprimir()
        myapp.show()
        sys.exit(app.exec_())
    
    
    def iniciar(*datos):
        app = QtWidgets.QApplication.instance()
        print (app)
        if app is None:
            app = QtWidgets.QApplication([])
        myapp = DialogoImprimir()
        myapp.show()
        return myapp.exec_()
    

    DialogoImprimir.py

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    MainModule = "__init__"
    
    import sys
    import imp
    import os
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class DialogoImprimir(QtWidgets.QDialog):
        def __init__(self):
            QtWidgets.QDialog.__init__(self)        
            self.GeneraUI()     
    
        def GeneraUI(self):
            self.setObjectName("Dialog")
            self.resize(200, 293)       
            self.buttonBox = QtWidgets.QDialogButtonBox(self)
            self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
            self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
            self.buttonBox.setObjectName("buttonBox")       
            self.retranslateUi()
            #acciones       
            self.buttonBox.accepted.connect(self.accept)
            self.buttonBox.rejected.connect(self.reject)
            QtCore.QMetaObject.connectSlotsByName(self)
    
        def retranslateUi(self):
            _translate = QtCore.QCoreApplication.translate
    

    main.cpp

    #include "mainwindow.h"    
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    

    mainwindows.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    };
    #endif // MAINWINDOW_H
    

    mainwindows.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "./pyrun.h"
    #include <QDebug>
    #include <QDir>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        QString pathPython = "/.pruebapython";
        QString pRuta = QDir::homePath()+pathPython;
        QString pModulo = "plugin_loader";
        QString pFuncion = "iniciar";
        QStringList pArgumentos;
        pArgumentos<<"1"<<"2"<<"3"<<"4";
        int res = ::PyRun::loadModule(QDir::home().absoluteFilePath(pRuta),pModulo, pFuncion, pArgumentos);
        qDebug()<<"Resultado: "<<res;
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    pyrun.h

    #ifndef PYRUN_H
    #define PYRUN_H
    
    
    //se crea un entorno para cargar modulos en python
    
    #include <QString>
    #include <QStringList>
    
    namespace PyRun
    {
    enum State
    {
        PythonUninitialized,
        PythonInitialized,
        AppModuleLoaded
    };
    enum Resultado
    {
        CannotLoadModule,
        CannotConvertArgument,
        CallFailed,
        CannotFindFunction,
        FailedToLoad,
        Success
    };
    
    int loadModule(const QString &modulePath, const QString &moduleName, const QString &functionName, const QStringList &args);
    State init();
    }
    #endif // PYRUN_H
    

    pyrun.cpp

    #include "pyrun.h"
    #include <Python.h>
    
    #include <QByteArray>
    #include <QCoreApplication>
    #include <QDebug>
    
    namespace PyRun
    {
    static State state = PythonUninitialized;
    
    static void cleanup()
    {
        if (state > PythonUninitialized) {
            Py_Finalize();
            state = PythonUninitialized;
        }
    }
    
    int loadModule(const QString &modulePath, const QString &moduleName, const QString &functionName, const QStringList& args)
    {
        qDebug()<<"modulepath"<<modulePath;
        qputenv("PYTHONPATH", modulePath.toLocal8Bit());
        if (init() != AppModuleLoaded)
            //return false;
            return CannotLoadModule;
        PyObject *pName, *pModule, *pFunc;
        PyObject *pArgs, *pValue;
        pName = PyUnicode_DecodeFSDefault(moduleName.toLocal8Bit().constData());
        /* Error checking of pName left out */
        pModule = PyImport_Import(pName);
        Py_DECREF(pName);
        if (pModule)
        {
            pFunc = PyObject_GetAttrString(pModule, functionName.toLocal8Bit().constData());
            /* pFunc is a new reference */
            if (pFunc && PyCallable_Check(pFunc))
            {
                /* pValue reference stolen here: */
                pArgs = PyTuple_New(args.size());
                for (int i = 0;i<args.size();i++)
                {
                    PyObject* arg_valor = Py_BuildValue("s",args.at(i).toLocal8Bit().constData());
                    if (!arg_valor)
                    {
                        Py_DECREF(pArgs);
                        Py_DECREF(pModule);
                        qWarning("Cannot convert argument\n");
                        //return false;
                        return  CannotConvertArgument;
                    }
                    PyTuple_SetItem(pArgs, i, arg_valor);//meto los datos de conexion
                }
                pValue = PyObject_CallObject(pFunc, pArgs);
                Py_DECREF(pArgs);
                if (pValue){
                    qWarning("Result of call: %ld\n", PyLong_AsLong(pValue));
                    Py_DECREF(pValue);
                }
                else
                {
                    Py_DECREF(pFunc);
                    Py_DECREF(pModule);
                    PyErr_Print();
                    qWarning("Call failed\n");
                    //return false;
                    return  CallFailed;
                }
            }
            else
            {
                if (PyErr_Occurred())
                    PyErr_Print();
                qWarning("Cannot find function \"%s\"\n", functionName.toLocal8Bit().constData());
            }
            Py_XDECREF(pFunc);
            Py_DECREF(pModule);
        }
        else
        {
            PyErr_Print();
            qWarning("Failed to load \"%s\"\n", moduleName.toLocal8Bit().constData());        
            //return false;
            return FailedToLoad;
        }
        //return true;
        return Success;
    }
    
    State init()
    {
        if (state > PythonUninitialized)
            return state;
        QByteArray virtualEnvPath = qgetenv("VIRTUAL_ENV");
        if (!virtualEnvPath.isEmpty())
            qputenv("PYTHONHOME", virtualEnvPath);
        Py_Initialize();
        qAddPostRoutine(cleanup);
        state = PythonInitialized;
        const bool pyErrorOccurred = PyErr_Occurred() != nullptr;
        if (!pyErrorOccurred) {
            state = AppModuleLoaded;
        } else {
            if (pyErrorOccurred)
                PyErr_Print();
            qWarning("Failed to initialize the module.");
        }
        return state;
    }
    }
    

    More things....the *.pro file has these lines (in my case):

    unix {
        INCLUDEPATH += /usr/include/python3.6m
        LIBS += -L /usr/local/lib/python3.6 -lpython3.6m
        DEPENDPATH +=  /usr/include/python3.6m
    }
    
    win32 {
        INCLUDEPATH += C:\Python\Python37\include
        LIBS += -L C:\Python\Python37\libs -lpython37
        DEPENDPATH += C:\Python\Python37\include
    }
    

    Actually, it is my clumsy version of the answer of this

    Well, running the script under linux there aren't any error, but under windows I have a white windows, without buttons or information on. Then the applicatios fails, and I must to force for close it.
    I have this message:

    QApplication::regClass: Registering window class 'Qt5ClipboardView' failed. (Esta clase ya existe.)

    And if I move the mouse over the white window I have these messages:

    windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x84 (WM_NCHITTEST), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x84 (WM_NCHITTEST), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x84 (WM_NCHITTEST), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x20 (WM_SETCURSOR), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x200 (WM_MOUSEMOVE), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x6 (WM_ACTIVATE), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x1c (WM_ACTIVATEAPP), hwnd=0x0xf0470.
    windowsProc: No Qt Window found for event 0x8 (WM_KILLFOCUS), hwnd=0x0xf0470.

    Sorry about my poor english.
    Thank you!


Log in to reply