擴展和嵌入python之重定向輸出與編譯

 

原創: PouG Pou光明 

 

在小長假的前一天要總結下最近的收穫。

Ok,按照之前兩篇嵌入和擴展python的文章來操作的話,現在已經可以定義自己的模塊、在運行時獲取異常信息。那麼問題來了,在編寫程序的過程中,難免有語法錯誤,如何在運行程序前檢查這些錯誤呢?在編寫大量python程序時,可以使用IDE輔助檢查,也可以使用靜態語法檢查工具。如果我們自己做python編輯器,肯定要有語法檢查的,總不能在運行時一直報語法錯誤,那會讓人崩潰的。。。還有今天要分享的另一個話題,如何在嵌入的解釋器中重新定向print()輸出,這個在操作上也是比較簡單。有了這兩個騷操作,基礎的功能就基本完成了。別高興太早,之後還有更頭疼的事情呢,比如,python解釋器被嵌入到了一個線程裏面,然後你要中斷此時線程裏面的操作。。。

重定向的功能實現起來比較方便,先貼這部分程序:

 

static PyObject *

aview_write(PyObject *self, PyObject *args)

{

    (void)self;

    char *what;

    if (!PyArg_ParseTuple(args, "s", &what))

    {

        return NULL;

    }

//    QString str(what);

    printf("--%s", what);

    return Py_BuildValue("");

}

 

static PyObject*

aview_flush(PyObject* self, PyObject* args)

{

    (void)self;

    (void)args;

    // no-op

    return Py_BuildValue("");

}

 

static PyMethodDef MathMethods[] = {

    {"add", add, METH_VARARGS,"add."},

    {"write", aview_write, METH_VARARGS,"aview_write."},

    {"flush", aview_flush, METH_VARARGS,"aview_flush."},

    {NULL, NULL, 0, NULL}

};

 

static PyModuleDef MathModule = {

    PyModuleDef_HEAD_INIT, "dahe", NULL, -1, MathMethods,

    NULL, NULL, NULL, NULL

};

 

static PyObject*

PyInit_math(void)

{

    PyObject* m = PyModule_Create(&MathModule);

    PySys_SetObject("stdout", m);

    PySys_SetObject("stderr", m);

    return m;

}

 

相比之前的程序,又添加了write和flush的函數,只添加write函數會有警告。還有就是在初始化模塊時有一些改動,將系統的標準輸出與標準錯誤輸出做了重定向。運行之前的程序結果如圖:

 

 

這樣我們靜態檢查的報錯信息也就可以獲得了。接下來介紹編譯的方法。

 

Python的py_compile模塊提供了一種將源文件生成字節代碼的方法,我們正是利用它的編譯功能去完成我們的靜態語法檢查。

 

#define COMPILEFILEPATH  "os.chdir('/root/Python/Article/redirect/pythonSource/')"

#define PYTHONPYCFILE "/root/Python/Article/redirect/compileDirectory/"

 

void Widget::on_pbn_compilePython_clicked()

{

    qDebug() << "compile python !";

    PyImport_AppendInittab("dahe", &PyInit_math);

 

    Py_Initialize();

    if (!Py_IsInitialized())

    {

        qDebug() << "inital faild!";

    }

 

    PyRun_SimpleString("import os");

    PyRun_SimpleString(COMPILEFILEPATH);

 

    PyRun_SimpleString("import dahe");

    PyRun_SimpleString("import py_compile");

 

    QString execFileName = "dhTest";

    QString pycFilePath = QString("py_compile.compile('%1.py','%2%1.pyc')").arg(execFileName).arg(PYTHONPYCFILE);

    char*  ch;

    QByteArray ba = pycFilePath.toLatin1();

    ch=ba.data();

    PyRun_SimpleString(ch);

 

    Py_Finalize();

}

 

上方是兩個路徑的宏,之前源代碼一直存放在可執行程序的目錄下,那也是默認的python工作目錄,現在我們改變了工作目錄。由於編譯會生成字節代碼文件,我們也爲這些文件指定了路徑。整個編譯的代碼是一個按鈕的槽函數。我們寫入錯誤的字符,運行編譯的功能,觀察效果。

 

UI圖示:

 

 

Python源文件:

點擊編譯按鈕運行結果:

 

 

點擊運行按鈕,此時是動態檢查結果:

 

 

這樣我們就實現了在運行前檢查語法錯誤的效果了。

 

程序還有很多不完善的地方,希望大家不吝賜教。多謝。

 

 

歡迎大家關注公衆號~

微信掃一掃
關注該公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章