[issue28202] Python 3.5.1 C API, the global variable is not destroyed when delete the module
Jack Liu
report at bugs.python.org
Tue Sep 20 01:48:35 EDT 2016
Jack Liu added the comment:
I wrote the test code as below. I also attached the files in attachment.
Python
=========================================================
class Simple:
def __init__( self ):
print('Simple__init__')
def __del__( self ):
print('Simple__del__')
simple = None
def run():
global simple
simple = Simple()
if __name__ == '__main__':
run()
==============================================================
C++
=========================================================================
#include "stdafx.h"
#include <Python.h>
#include <string>
#include <iostream>
#include <fstream>
#include <codecvt>
#include <map>
using namespace std;
namespace {
wstring readfile(const wchar_t *filename)
{
wifstream wifs;
wifs.open(filename);
//wifs.imbue(locale(wifs.getloc(), new codecvt_utf8<wchar_t, 0x10ffff, consume_header>()));
wstring wstr((std::istreambuf_iterator<wchar_t>(wifs)),
std::istreambuf_iterator<wchar_t>());
return wstr;
}
string wstrtostr(const wstring& ws)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(ws);
}
}
int main()
{
cout << "Input py file full path:" << endl;
wstring filePath;
wcin >> filePath;
//filePath = L"L:\\Dev\\PyTest\\SimpleTest.py";
string moduleName = "__main__";
string script = wstrtostr(readfile(filePath.c_str()));
if (script.empty())
{
cout << "Invalid python file path" << endl;
return 1;
}
string sfileName = wstrtostr(filePath);
// Initialize the Python Interpreter
Py_Initialize();
PyObject *py_module = PyImport_AddModule(moduleName.c_str());
PyObject *py_dict = PyModule_GetDict(py_module);
PyObject* res = nullptr;
auto arena = PyArena_New();
if (arena)
{
auto mod = PyParser_ASTFromString(script.c_str(), sfileName.c_str(), Py_file_input, nullptr, arena);
if (mod)
{
auto co = PyAST_Compile(mod, sfileName.c_str(), nullptr, arena);
if (co)
{
res = PyEval_EvalCode((PyObject*)(co), py_dict, py_dict);
Py_DECREF(co);
}
}
PyArena_Free(arena);
}
if (res)
{
Py_DECREF(res);
}
// Delete the module from sys.modules
PyObject* modules = PyImport_GetModuleDict();
cout << "PyDict_DelItemString" << endl;
PyDict_DelItemString(modules, moduleName.c_str());
// May run many scripts here
// Finish the Python Interpreter
cout << "Py_Finalize" << endl;
Py_Finalize();
return 0;
}
===================================================================
The expected output in console should be:
Simple__init__
PyDict_DelItemString
Simple__del__
Py_Finalize
I tested with Python 3.2.5, 3.3.5, 3.5.1 and 3.6.0 beta.
It worked as expected with Python 3.2.5 and 3.3.5, but did not work Python 3.5.1 and 3.6.0 beta.
On Python 3.5.1 and 3.6.0 beta, the output is:
Simple__init__
PyDict_DelItemString
Py_Finalize
Simple__del__
That means the Simple object is not released at PyDict_DelItemString, it's released at Py_Finalize.
So it it a regression bug since Python 3.5? I wish there is a solution to resolve memory leak issue.
----------
Added file: http://bugs.python.org/file44748/PyTest.zip
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue28202>
_______________________________________
More information about the Python-bugs-list
mailing list