• 如何写一个Python Interpreter


    最近一直在捣鼓Python,老想学别人在自己的SolidMCP之类搞一个Python Interpreter。

    起初觉得很高深,就直接把将某开源软件基于Qt的Python Console实现剥离开来,成功移植到SolidMCP内。

    在这个过程中发现,其实写一个蹩脚的Python Interpreter并不是太难,Piaoger决定沉下心来,研究一把,并把研究成果记录下来如下:

    >> 如何写一个Python Interpreter

    可以先用Python来写一个Prototype,再用C++翻译过来就是啦。

    import sys
    import os
    import code
    
    redirectedOutput = r'C:\RedirectedPythonConsole.txt'
    
    # Redirected Channel
    class MyConsole:
        def write(self, input):        
            myFile = file(redirectedOutput, 'a')
            output = '\nPython>' + input
            myFile.write(output)
            myFile.close()
    
    # Redirect stdout to MyConsole
    defaultStdOut = sys.stdout
    myConsole = MyConsole()
    sys.stdout = myConsole
    if os.path.exists(redirectedOutput):
        os.remove(redirectedOutput)        
    
    # Compile input code to code object
    # Run Code Object
    inputCode = '2+3'
    interpreter = code.InteractiveInterpreter()
    codeObject = interpreter.compile(inputCode)
    interpreter.runcode(codeObject)
    
    sys.stdout = myConsole

    >>C++版本原型

        // Demonstrates how to use Interactive Interpreter and Interactive Console
        void testInterpreter()
        {
            Py_Initialize();
    
            // #load code module to use InteractiveInterpreter and InteractiveConsole
            // # Utilities used to emulate Python's interactive interpreter
            // # InteractiveConsole closely emulates the behavior of the interactive Python interpreter
            // # InteractiveConsole builds on InteractiveInterpreter
    
            // import code module
            PyObject* module = PyImport_ImportModule("code");
    
            // Construct InteractiveInterpreter from code module
            PyObject* func = PyObject_GetAttrString(module, "InteractiveInterpreter");
            PyObject* args = Py_BuildValue("()");
            PyObject* interpreter = PyEval_CallObject(func,args);
    
            // Provide input as code
            const char* source = "2+3";
            PyObject* sourceArgs = Py_BuildValue("(s)", source);
            PyObject* compilefunc = PyObject_GetAttrString(interpreter, "compile");
            PyObject* codeObject = PyEval_CallObject(compilefunc, sourceArgs);
    
            // run compiled bytecode
            PyObject* mainModule = PyImport_AddModule("__main__");
            PyObject* dict = PyModule_GetDict(mainModule);
            PyObject* presult = PyEval_EvalCode((PyCodeObject*)codeObject, dict, dict);
    
            // Finally, release everything by decrementing their reference counts.
            //
            Py_DECREF(mainModule);
            Py_DECREF(presult);
            Py_DECREF(dict);
    
            Py_DECREF(codeObject);
            Py_DECREF(compilefunc);
            Py_DECREF(sourceArgs);
    
            Py_DECREF(interpreter);
            Py_DECREF(args);
            Py_DECREF(func);
    
            Py_Finalize();
        }

    基本上原理就是这样的,其余的事情不外乎也搞一个sys.stdout的重定向,然后就是处理TextEdit控件的事件啦。

    >> 利用InteractiveConsole直接用Python写

    Python提供了一个InteractiveConsole帮我们来干这个事情,这玩意其实也是继承自InteractiveInterpreter.

    那些基于PyQt的Python Console大抵就是这样干的。

    # -----------------------------------------------------------------------------------------------
    # Copy from ActiveState Code Recipes
    # http://code.activestate.com/recipes/355319-using-codeinteractiveconsole-to-embed-a-python-she/
    # -----------------------------------------------------------------------------------------------
    import
    sys import code from code import InteractiveConsole class FileCacher: "Cache the stdout text so we can analyze it before returning it" def __init__(self): self.reset() def reset(self): self.out = [] def write(self,line): self.out.append(line) def flush(self): output = '\n'.join(self.out) self.reset() return output class Shell(InteractiveConsole): "Wrapper around Python that can filter input/output to the shell" def __init__(self): self.stdout = sys.stdout self.cache = FileCacher() InteractiveConsole.__init__(self) return def get_output(self):
    sys.stdout = self.cache
    def return_output(self):
    sys.stdout = self.stdout def push(self,line): self.get_output() # you can filter input here by doing something like # line = filter(line) InteractiveConsole.push(self,line) self.return_output() output = self.cache.flush() # you can filter the output here by doing something like # output = filter(output) print output # or do something else with it return if __name__ == '__main__': sh = Shell() sh.interact()
  • 相关阅读:
    Linux Ubuntu系统的安装||grub启动字符界面
    linux 第一个qt程序 以及 linux qt cannotfind lgL的解决
    linux ftp 文件传输的搭建 以qt上传为例
    linux gcc 安装和第一个hello world脚本
    python bug debug
    python 元组的概念以及 math 模块
    移动端调试
    移动终端学习2:触屏原生js事件及重力感应
    input file 类型为excel表格
    gulp构建工具的安装
  • 原文地址:https://www.cnblogs.com/piaoger/p/2513576.html
Copyright © 2020-2023  润新知