为什么PyRun_SimpleString不释放内存

问题描述

我最近正在学习CPython,并且已经编写了有关我所学内容的守护程序。

首先,我创建自定义PytestClass类型并将其作为内置模块导入。然后,我调用PyRun_SimpleString运行使用PytestClass的脚本,但是我发现PytestClass的析构函数直到Py_Finalize都不会被调用。谁能解释这个问题,并且在脚本运行后如何清除内存?我担心内存泄漏。

#include "Python.h"
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>


PyMethodDef PyFlatExecutionMethods[] = {
    {NULL,NULL,NULL}
};

typedef struct PytestExecution {
   PyObject_HEAD
   int a;
}PytestExecution;

static PyObject *PytestExecution_ToStr(PyObject * pyObj){
    return PyUnicode_FromString("PytestExecution");
}

static void PytestExecution_Destruct(PyObject *pyObj){
    //PytestExecution* pfep = (PytestExecution*)pyObj;
    printf("PytestExecution_Destruct\n");
    Py_TYPE(pyObj)->tp_free((PyObject*)pyObj);
}


static PyTypeObject PytestClass = {
    PyVarObject_HEAD_INIT(NULL,0)
    "rrunner.PytestExecution",/* tp_name */
    sizeof(PytestExecution),/* tp_basicsize */
    0,/* tp_itemsize */
    PytestExecution_Destruct,/* tp_dealloc */
    0,/* tp_print */
    0,/* tp_getattr */
    0,/* tp_setattr */
    0,/* tp_compare */
    0,/* tp_repr */
    0,/* tp_as_number */
    0,/* tp_as_sequence */
    0,/* tp_as_mapping */
    0,/* tp_hash */
    0,/* tp_call */
    PytestExecution_ToStr,/* tp_str */
    0,/* tp_getattro */
    0,/* tp_setattro */
    0,/* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* tp_flags */
    "PytestExecution",/* tp_doc */
};

static PyModuleDef EmbrRunner = {
    PyModuleDef_HEAD_INIT,"rrunner","export methods provide by rrunner.",-1,NULL
};

static PyObject* PyInit_rRunner(void) {
    return PyModule_Create(&EmbrRunner);
}

static PyObject* runnerCtx(PyObject *cls,PyObject *args){
    return NULL;
}

PyMethodDef EmbrtestMethods[] = {
    {"runnerCtx",runnerCtx,METH_VARARGS,"runner context"},{NULL,NULL}
};


char *script = "from rrunner import Pytest;\ndef abc():\n\tprint('in abc 1')\nabc()\nbc=Pytest()\nbc.map()\n";
char *script2 = "import sys;\ndef abc():\n\tprint('in abc 2')\nabc()\nbc2=Pytest()";
char *script3 = "import sys;\ndef abc():\n\tprint('in abc 2')\nabc()\nbc3=Pytest()";
char *script4 = "import sys;\ndef abc():\n\tprint('in abc 2')\nabc()\nbc4=Pytest()";

int main()
{

    EmbrRunner.m_methods = EmbrtestMethods;
    EmbrRunner.m_size = sizeof(EmbrtestMethods) / sizeof(*EmbrtestMethods);
    PyImport_AppendInittab("rrunner",&PyInit_rRunner);


    Py_Initialize();
    PyEval_InitThreads();



    PytestClass.tp_new = PyType_GenericNew;
    PytestClass.tp_methods = PyFlatExecutionMethods;
    if (PyType_Ready(&PytestClass) < 0){
        printf("regiester error\n");
        return 0;
    }
    Py_INCREF(&PytestClass);

    PyObject *pName = PyUnicode_FromString("rrunner");
    PyObject* rRunnerModule = PyImport_Import(pName);
    Py_DECREF(pName);
    PyModule_AddObject(rRunnerModule,"Pytest",(PyObject *)&PytestClass);

    int a = PyRun_SimpleString(script);
    a = PyRun_SimpleString(script2);
    a = PyRun_SimpleString(script3);
    a = PyRun_SimpleString(script4);

    printf("After dup run\n");
    a = PyRun_SimpleString(script4);
    printf("After run\n");

    Py_Finalize();
}

此外,我对实现可以运行从客户端发送的脚本的应用程序感兴趣。在CPython 下是否有任何解决方案,我只是想要彼此隔离的脚本(为每个脚本创建一个新的解释器太耗时了)?我发现子解释器可能成为解决方案,但没有找到示例。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...