简体   繁体   English

如何重新初始化嵌入式Python解释器?

[英]How to reinitialise an embedded Python interpreter?

I'm working on embedding Python in our test suite application. 我正在努力在我们的测试套件应用程序中嵌入Python。 The purpose is to use Python to run several tests scripts to collect data and make a report of tests. 目的是使用Python运行多个测试脚本来收集数据并生成测试报告。 Multiple test scripts for one test run can create global variables and functions that can be used in the next script. 一次测试运行的多个测试脚本可以创建可在下一个脚本中使用的全局变量和函数。

The application also provides extension modules that are imported in the embedded interpreter, and are used to exchange some data with the application. 该应用程序还提供在嵌入式解释器中导入的扩展模块,用于与应用程序交换某些数据。

But the user can also make multiple test runs. 但是用户也可以进行多次测试运行。 I don't want to share those globals, imports and the exchanged data between multiple test runs. 我不想在多次测试运行之间共享那些全局变量,导入和交换的数据。 I have to be sure I restart in a genuine state to control the test environment and get the same results. 我必须确保我以真实状态重新启动以控制测试环境并获得相同的结果。

How should I reinitialise the interpreter? 我该如何重新初始化翻译?

I used Py_Initialize() and Py_Finalize(), but get an exception on the second run when initialising a second time the extension modules I provide to the interpreter. 我使用了Py_Initialize()和Py_Finalize(),但在第二次运行时,我第二次将我提供给解释器的扩展模块初始化时获得异常。 And the documentation warns against using it more than once . 文档警告不要多次使用它

Using sub-interpreters seems to have the same caveats with extension modules initialization. 使用子解释器似乎与扩展模块初始化具有相同的警告。

I suspect that I'm doing something wrong with the initialisation of my extension modules, but I fear that the same problem happens with 3rd party extension modules. 我怀疑我的扩展模块初始化时出了问题,但我担心第三方扩展模块会出现同样的问题。

Maybe it's possible to get it to work by launching the interpreter in it's own process, so as to be sure that all the memory is released. 也许可以通过在其自己的进程中启动解释器来使其工作,以确保释放所有内存。

By the way, I'm using boost-python for it, that also warns AGAINST using Py_Finalize! 顺便说一句,我正在使用boost-python,它也使用Py_Finalize警告AGAINST!

Any suggestion? 有什么建议吗?

Thanks 谢谢

Here is another way I found to achieve what I want, start with a clean slate in the interpreter. 这是我发现实现我想要的另一种方式,从解释器中的一个干净的石板开始。

I can control the global and local namespaces I use to execute the code: 我可以控制用于执行代码的全局和本地命名空间:

// get the dictionary from the main module
// Get pointer to main module of python script
object main_module = import("__main__");
// Get dictionary of main module (contains all variables and stuff)
object main_namespace = main_module.attr("__dict__");

// define the dictionaries to use in the interpreter
dict global_namespace;
dict local_namespace;

// add the builtins
global_namespace["__builtins__"] = main_namespace["__builtins__"];

I can then use use the namespaces for execution of code contained in pyCode : 然后我可以使用命名空间来执行pyCode包含的代码:

exec( pyCode, global_namespace, lobaca_namespace );

I can clean the namespaces when I want to run a new instance of my test, by cleaning the dictionaries: 当我想通过清理字典来运行我的测试的新实例时,我可以清理命名空间:

// empty the interpreters namespaces
global_namespace.clear();
local_namespace.clear();        

// Copy builtins to new global namespace
global_namespace["__builtins__"] = main_namespace["__builtins__"];

Depending at what level I want the execution, I can use global = local 根据我想要执行的级别,我可以使用global = local

How about using code.IteractiveInterpreter ? 如何使用code.IteractiveInterpreter

Something like this should do it: 这样的事情应该这样做:

#include <boost/python.hpp>
#include <string>
#include <stdexcept>

using namespace boost::python;

std::string GetPythonError()
{
    PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL;
    PyErr_Fetch(&ptype, &pvalue, &ptraceback);
    std::string message("");
    if(pvalue && PyString_Check(pvalue)) {
        message = PyString_AsString(pvalue);
    }
    return message;
}

// Must be called after Py_Initialize()
void RunInterpreter(std::string codeToRun)
{
    object pymodule = object(handle<>(borrowed(PyImport_AddModule("__main__"))));
    object pynamespace = pymodule.attr("__dict__");

    try {
        // Initialize the embedded interpreter
        object result = exec(   "import code\n"
                                "__myInterpreter = code.InteractiveConsole() \n", 
                                pynamespace);
        // Run the code
        str pyCode(codeToRun.c_str());
        pynamespace["__myCommand"] = pyCode;
        result = eval("__myInterpreter.push(__myCommand)", pynamespace);
    } catch(error_already_set) {
        throw std::runtime_error(GetPythonError().c_str());
    }
}

I'd write another shell script executing the sequence of test scripts with new instances of python each time. 我会编写另一个shell脚本,每次都使用新的python实例执行测试脚本序列。 Or write it in python like 或者用python写它

# run your tests in the process first
# now run the user scripts, each in new process to have virgin env
for script in userScript:
    subprocess.call(['python',script])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何中断C ++应用程序中嵌入的python解释器 - How to interrupt python interpreter embedded in C++ application 带有嵌入式 Python 解释器的未定义符号错误 - Undefined Symbol Error with embedded Python interpreter python - C++ 嵌入式解释器和对象 - python - c++ embedded interpreter and objects 如何为嵌入式python解释器设置工作目录 - Howto set working directory for embedded python interpreter 如何将单个PyObject(在C ++后端中创建)传递给嵌入式Python解释器? - How can I pass a single PyObject (created in a C++ backend) to an embedded Python Interpreter? 如何允许嵌入式Python解释器中调用的脚本导入第三方库? - How to allow 3rd-party libraries to be imported by scripts called in embedded Python interpreter? 如何使用嵌入式python解释器(pybind11)构建和执行cpp文件 - How to build and execute a cpp file with embedded python interpreter(pybind11) 如何使用C ++中的字节码优化来初始化嵌入式Python解释器? - How can I initialize an embedded Python interpreter with bytecode optimization from C++? 使用c ++对象的全局实例扩展嵌入式python解释器 - Extending an embedded python interpreter with global instance of a c++ object 从 C++ 嵌入式解释器捕获 python 窗口输出 - Capturing python windowed output from C++ embedded interpreter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM