2016-07-24 167 views
1

我搞砸了,试图构建类似于IPython/Jupyter笔记本的东西。我在QT5中编写我的应用程序,其中很大一部分与将Python嵌入到本机应用程序中有关。导入matplotlib.pyplot后导致嵌入式python崩溃

我想出了如何嵌入python以及如何让它执行用户输入的脚本。我希望能够使用绘图库(如matplotlib),并在我的应用程序中显示它们的输出。 (实际上,我试图做的事似乎与this question中描述的非常相似)。但是,当我尝试导入绘图库使用import matplotlib.pyplot,我的应用程序段错误(我试过调试,但崩溃不在我的代码中,所以我不能得到任何明智的东西)。

这个问题的底部显示了我用来初始化嵌入式Python以及运行任意脚本的代码。

我可以导入其他库(如sysnumpy)罚款。我可以输入matplotlib罚款。但是当我尝试导入matplotlib.pyplot时,它会出现段错误。

有没有人有任何建议?

编辑: 我确定原因在于(出于某种原因)与我一起使用QT。当我编译一个简单的C或C++程序,导入matplotlib,它段错误...

我的代码:

#include "pythoninteractor.h" 

#include <QString> 
#include <Python.h> 
#include <string> 
#include <QList> 

PythonInteractor::PythonInteractor() 
{ 
    this->pyOutput_redir = 
"import sys\n\ 
class CatchOutErr:\n\ 
    def __init__(self):\n\ 
     self.value = ''\n\ 
    def write(self, txt):\n\ 
     self.value += txt\n\ 
catchOutErr = CatchOutErr()\n\ 
sys.stdout = catchOutErr\n\ 
sys.stderr = catchOutErr\n\ 
"; //this is python code to redirect stdouts/stderr 


    QString paths[] = {"", 
         "/home/tcpie/anaconda3/lib/python35.zip", 
         "/home/tcpie/anaconda3/lib/python3.5", 
         "/home/tcpie/anaconda3/lib/python3.5/plat-linux", 
         "/home/tcpie/anaconda3/lib/python3.5/lib-dynload", 
         "/home/tcpie/anaconda3/lib/python3.5/site-packages",}; 

    Py_SetProgramName(L"qt-notepad-tut"); 
    Py_Initialize(); 

    PyObject *pModule = PyImport_AddModule("__main__"); //create main module 
    PyRun_SimpleString(this->pyOutput_redir.toStdString().c_str()); //invoke code to redirect 

    PyObject *sys_path; 
    PyObject *path; 

    sys_path = PySys_GetObject("path"); 
    if (sys_path == NULL) 
     return; 

    PySequence_DelSlice(sys_path, 0, PySequence_Length(sys_path)); 
    for (size_t i = 0; i < sizeof(paths)/sizeof(QString); i++) { 
     path = PyUnicode_FromString(paths[i].toStdString().c_str()); 

     if (path == NULL) 
      continue; 

     if (PyList_Append(sys_path, path) < 0) 
      continue; 
    } 
} 

QString PythonInteractor::run_script(QString script) 
{ 
    QString ret = ""; 
    PyObject *pModule = PyImport_AddModule("__main__"); 
    PyRun_SimpleString(script.toStdString().c_str()); 
    PyErr_Print(); //make python print any errors 

    PyObject *catcher = PyObject_GetAttrString(pModule,"catchOutErr"); //get our catchOutErr created above 

    if (catcher == NULL) { 
     Py_Finalize(); 
     return ret; 
    } 

    PyObject *output = PyObject_GetAttrString(catcher,"value"); //get the stdout and stderr from our catchOutErr object 

    if (output == NULL) { 
     return ret; 
    } 

    ret = QString(PyUnicode_AsUTF8(output)); 
    return ret; 
} 
+0

你为什么试图嵌入Python? – user4759923

+0

我想看看是否可以制作类似于IPython笔记本的东西,但在本机应用程序中。 – tcpie

+0

我怀疑这是否合理(Qt非常好) – user4759923

回答

2

此崩溃的原因竟然是QT版本之间有冲突。

首先,可以使用以下最小代码复制问题。在main.h中注释掉“Q_OBJECT”行可以防止所有情况下的崩溃。

文件main.h:

#ifndef MAIN_H 
#define MAIN_H 

#include <QMainWindow> 

class test : public QMainWindow 
{ 
    Q_OBJECT // Commenting out this line prevents the crash 
}; 

#endif // MAIN_H 

文件main.cpp中:

#include <Python.h> 
#include "main.h" 

int main() 
{ 
    Py_Initialize(); 
    PyRun_SimpleString("import matplotlib.pyplot as plt");  
    PyRun_SimpleString("print('If we are here, we did not crash')"); 

    Py_Finalize(); 
    return 0; 
} 

我通过蟒蛇跑Python3。但是,我通过我的软件包管理器(在我的情况下是Ubuntu上的apt-get)安装了QT5。我怀疑问题在于我的Anaconda安装的matplotlib使用与我通过我的软件包管理器安装的版本不同的QT5版本。

修复很简单:通过我的包管理器安装matplotlib修复了问题! (在我的Ubuntu系统上:sudo apt-get install python3-matplotlib