使用 Py_SetPath() 和 Py_GetPath() 后 Python C API free() 错误
Python C API free() errors after using Py_SetPath() and Py_GetPath()
我想弄清楚为什么我不能通过其 C API 简单地获取和设置 python 路径。我在 Ubuntu 17.10 上使用 Python3.6,gcc 版本为 7.2.0。编译:
gcc pytest.c `python3-config --libs` `python3-config --includes`
#include <Python.h>
int main()
{
Py_Initialize(); // removes error if put after Py_SetPath
printf("setting path\n"); // prints
Py_SetPath(L"/usr/lib/python3.6"); // Error in `./a.out': free(): invalid size: 0x00007fd5a8365030 ***
printf("success\n"); // doesn't print
return 0;
}
设置路径工作正常,除非我也尝试在这样做之前获取路径。如果我完全获得路径,即使只是打印而不修改返回值或任何其他内容,我也会收到 "double free or corruption" 错误。
很困惑。我做错了什么还是这是一个错误?有人知道解决方法吗?
编辑:调用 Py_Initialize();
后也出现错误。更新代码。现在即使我不先调用 Py_GetPath() 也会出错。
[以下答案参考this version of the question。]
来自docs:
void Py_Initialize()
Initialize the Python interpreter. In an application embedding Python, this should be called before using any other Python/C API functions; with the exception of Py_SetProgramName()
, Py_SetPythonHome()
and Py_SetPath()
.
但是您显示的代码在调用 Py_Initialize();
之前确实调用了 Py_GetPath()
,根据上一段,它隐含地不应该调用。
从 alk 看来它与这个错误有关:https://bugs.python.org/issue31532
这是我正在使用的解决方法。因为你不能在Py_Initialize()
之前调用Py_GetPath()
,而且貌似你不能在Py_Initialize()
之后调用Py_SetPath()
,你可以在调用之后添加或获取这样的路径Py_Initialize()
:
#include <Python.h>
int main()
{
Py_Initialize();
// get handle to python sys.path object
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
// make a list of paths to add to sys.path
PyObject *newPaths = PyUnicode_Split(PyUnicode_FromWideChar(L"a:b:c", -1), PyUnicode_FromWideChar(L":", 1), -1);
// iterate through list and add all paths
for(int i=0; i<PyList_Size(newPaths); i++) {
PyList_Append(path, PyList_GetItem(newPaths, i));
}
// print out sys.path after appends
PyObject *newlist = PyUnicode_Join(PyUnicode_FromWideChar(L":", -1), path);
printf("newlist = %ls\n", PyUnicode_AsWideCharString(newlist, NULL));
return 0;
}
我想弄清楚为什么我不能通过其 C API 简单地获取和设置 python 路径。我在 Ubuntu 17.10 上使用 Python3.6,gcc 版本为 7.2.0。编译:
gcc pytest.c `python3-config --libs` `python3-config --includes`
#include <Python.h>
int main()
{
Py_Initialize(); // removes error if put after Py_SetPath
printf("setting path\n"); // prints
Py_SetPath(L"/usr/lib/python3.6"); // Error in `./a.out': free(): invalid size: 0x00007fd5a8365030 ***
printf("success\n"); // doesn't print
return 0;
}
设置路径工作正常,除非我也尝试在这样做之前获取路径。如果我完全获得路径,即使只是打印而不修改返回值或任何其他内容,我也会收到 "double free or corruption" 错误。
很困惑。我做错了什么还是这是一个错误?有人知道解决方法吗?
编辑:调用 Py_Initialize();
后也出现错误。更新代码。现在即使我不先调用 Py_GetPath() 也会出错。
[以下答案参考this version of the question。]
来自docs:
void Py_Initialize()
Initialize the Python interpreter. In an application embedding Python, this should be called before using any other Python/C API functions; with the exception of
Py_SetProgramName()
,Py_SetPythonHome()
andPy_SetPath()
.
但是您显示的代码在调用 Py_Initialize();
之前确实调用了 Py_GetPath()
,根据上一段,它隐含地不应该调用。
从 alk 看来它与这个错误有关:https://bugs.python.org/issue31532
这是我正在使用的解决方法。因为你不能在Py_Initialize()
之前调用Py_GetPath()
,而且貌似你不能在Py_Initialize()
之后调用Py_SetPath()
,你可以在调用之后添加或获取这样的路径Py_Initialize()
:
#include <Python.h>
int main()
{
Py_Initialize();
// get handle to python sys.path object
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
// make a list of paths to add to sys.path
PyObject *newPaths = PyUnicode_Split(PyUnicode_FromWideChar(L"a:b:c", -1), PyUnicode_FromWideChar(L":", 1), -1);
// iterate through list and add all paths
for(int i=0; i<PyList_Size(newPaths); i++) {
PyList_Append(path, PyList_GetItem(newPaths, i));
}
// print out sys.path after appends
PyObject *newlist = PyUnicode_Join(PyUnicode_FromWideChar(L":", -1), path);
printf("newlist = %ls\n", PyUnicode_AsWideCharString(newlist, NULL));
return 0;
}