У меня есть некоторый код, который будет идти в каталог (папка 1 для демонстрационных целей), а затем вызвать функцию под названием function
в файле python_function.py
, Код выглядит так:
#include <Python.h>
#include <string>
#include <iostream>
int main()
{
PyObject *pName, *pModule, *pDict, *pFunc;
setenv("PYTHONDONTWRITEBYTECODE", " ", 1);
// Initialize the Python Interpreter
Py_Initialize();
//CALL FUNCTION FROM FOLDER 1:
std::wstring pathWide = L"./Folder 1";
PySys_SetPath(pathWide.c_str());
// Build the name object
pName = PyUnicode_FromString((char*)"python_function");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"function");
if (pFunc != NULL)
{
if (PyCallable_Check(pFunc))
{
PyObject *pResult;
pResult = PyObject_CallFunction(pFunc, "");
Py_DECREF(pResult);
}
else {PyErr_Print();}
}
else {std::cout << "pFunc is NULL!" << std::endl;}
// Clean up
Py_DECREF(pFunc);
Py_DECREF(pDict);
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
return 0;
}
Этот код компилируется и отлично работает в моей системе, но как только я хочу вызвать другую функцию во втором каталоге, которая называется Папка 2, я получаю ошибку: Segmentation Fault (core dumped)
, Это код:
#include <Python.h>
#include <string>
#include <iostream>
int main()
{
PyObject *pName, *pModule, *pDict, *pFunc;
setenv("PYTHONDONTWRITEBYTECODE", " ", 1);
// Initialize the Python Interpreter
Py_Initialize();
//CALL FUNCTION FROM FOLDER 1:
std::wstring pathWide = L"./Folder 1";
PySys_SetPath(pathWide.c_str());
// Build the name object
pName = PyUnicode_FromString((char*)"python_function");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"function");
if (pFunc != NULL)
{
if (PyCallable_Check(pFunc))
{
PyObject *pResult;
pResult = PyObject_CallFunction(pFunc, "");
Py_DECREF(pResult);
}
else {PyErr_Print();}
}
else {std::cout << "pFunc is NULL!" << std::endl;}
//CALL FUNCTION FROM FOLDER 2:
pathWide = L"./Folder 2";
PySys_SetPath(pathWide.c_str());
// Build the name object
pName = PyUnicode_FromString((char*)"python_function");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"function");
if (pFunc != NULL)
{
if (PyCallable_Check(pFunc))
{
PyObject *pResult;
pResult = PyObject_CallFunction(pFunc, "");
Py_DECREF(pResult);
}
else {PyErr_Print();}
}
else {std::cout << "pFunc is NULL!" << std::endl;}
// Clean up
Py_DECREF(pFunc);
Py_DECREF(pDict);
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
return 0;
}
Ошибка возникает после того, как я вызываю первую функцию, поэтому кажется, что она не меняет каталоги или что-то в этом роде. Я использую Ubuntu и у меня есть Python 3.4
Я пробовал другие способы изменения каталогов, не только PySys_SetPath
, но также setenv("PYTHONPATH", path, 1);
ПРИМЕЧАНИЕ: я не беспокоюсь об обнаружении ошибок сейчас, я предпочел бы иметь код, который работает в идеальных условиях, а затем беспокоиться о несовершенных обстоятельствах.
РЕДАКТИРОВАТЬ:
Отладочный вывод:
#0 0x7ffff79b16cb PyModule_GetDict() (/usr/lib/x86_64-linux-gnu/libpython3.4m.so.1.0:??)
#1 0x4010e6 main() (/home/ben/Documents/Programming/Projects/PYTHON TEST/main.cpp:23)
Как ни странно, отладка говорит, что ошибка происходит в строке 23, но строка 23 не вызывает ошибку, если вы запускаете первый сегмент кода
В ответ на ответ Петра Бриттена:
Если я заменю второй PyImport_Import()
с PyImport_ReloadModule()
Я получаю сообщение об ошибке на консоли, например:
ImportError: No module named 'imp'
Error in sys.excepthook:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 53, in apport_excepthook
if not enabled():
File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 24, in enabled
import re
ImportError: No module named 're'
Original exception was:
ImportError: No module named 'imp'
РЕДАКТИРОВАТЬ: Обновлено с дальнейшими ответами на найденные ошибки.
Вы не можете импортировать свой модуль в выходные данные отладки. При запуске вне отладчика вы сталкиваетесь с проблемой, которую вы не можете просто импортировать, с помощью того же вызова импорта. Полная цепочка проблем примерно такая.
При отладке:
PySys_SetPath()
,PyImport_Import()
указывает на то, что импорт не удается (как задокументировано Вот под отладчиком.Я столкнулся с проблемой с Python2.7 (используя char * вместо wchar * — как описано в комментариях ниже). Поместив это в сторону, когда работает нормально:
PySys_SetPath()
,PyImport_ReloadModule()
вместо.Итак, исправления:
std::string
вместо std::wstring
(для Python 2.x).PyImport_ReloadModule()
при перезагрузке модулей.PyErr_Print()
для большинства проблем.