Почему происходит сбой Python / C API на PyRun_SimpleFile? - PullRequest
12 голосов
/ 07 сентября 2010

Я экспериментировал с внедрением различных языков сценариев в приложение C ++, в настоящее время я пробую Stackless Python 3.1. Я пробовал несколько учебных пособий и примеров, которые я могу найти, чтобы попытаться запустить простой скрипт из приложения.

Py_Initialize();

FILE* PythonScriptFile = fopen("Python Scripts/Test.py", "r");
if(PythonScriptFile)
{
    PyRun_SimpleFile(PythonScriptFile, "Python Scripts/Test.py");
    fclose(PythonScriptFile);
}

Py_Finalize();

По какой-то странной причине запуск этого фрагмента кода приводит к нарушению доступа по адресу:

    PyRun_SimpleFile(PythonScriptFile, "Python Scripts/Test.py");

Я искал в Интернете других с похожей проблемой и нашел только одну. Их единственным решением был обходной путь, который кажется возможным только в более старой версии Python: создание объекта файла python и возврат FILE* из этого объекта файла python в PyRun_SimpleFile. Однако такие вызовы функций недоступны, API Python 3.1 создает файловые объекты из файлового дескриптора и возвращает файловые дескрипторы, но функция PyRun_SimpleFile все еще требует FILE*.

Я в растерянности относительно того, как запускать любые сценарии из файла, если не считать загрузки всего файла в память вручную и запуска его в виде гигантской строки, что, конечно, не практичное решение.

Что дает? Как я могу выполнить эту задачу, если в API есть внутренняя ошибка?

Обновление: Мне удалось собрать Stackless Python 3.1 из исходного кода, и все же сбой остался полностью неизменным, несмотря на использование той же библиотеки времени выполнения C. И мой проект, и исходник Stackless Python 3.1 созданы с помощью компилятора Visual Studio 2010 C ++ и среды выполнения C. У меня больше нет никаких мыслей относительно того, что может решить эту проблему, если не считать изменения в Python для использования имени файла, а не ФАЙЛА *. Еще один ужасный обходной путь.

Ответы [ 7 ]

12 голосов
/ 14 сентября 2011

Я получил похожий сбой и сделал следующее:

   PyObject* PyFileObject = PyFile_FromString("test.py", "r");
   PyRun_SimpleFileEx(PyFile_AsFile(PyFileObject), "test.py", 1);

Обратите внимание, что это было в python 2.7 . Я не знаю, изменился ли API в 3.x.

9 голосов
/ 09 марта 2012

Это работает для меня на Python 3:

 PyObject *obj = Py_BuildValue("s", "test.py");
 FILE *file = _Py_fopen_obj(obj, "r+");
 if(file != NULL) {
     PyRun_SimpleFile(file, "test.py");
 }

Надеюсь, это будет полезно.

5 голосов
/ 07 сентября 2010

Ваш код работает правильно на моей установленной версии Python 2.6.Я также собрал 3.1.2 без стека из исходного кода, и он работал правильно.Это было с g ++ 4.4.3 на Ubuntu 10.04.Если вы работаете в Windows, вы можете проверить, что и стек без стека, и ваш код созданы для одной и той же среды выполнения C.

3 голосов
/ 07 сентября 2010

Это звучит как проблема несовпадающих API.Если ваш код и среда выполнения Python были скомпилированы с использованием разных компиляторов или даже разных опций компилятора, то доступ к FILE * может привести к нарушению доступа.Можете ли вы еще раз проверить, правильно ли вы создали свой код C?

Вы упоминаете, что встраиваете Python в свое приложение C ++.Имейте в виду, что Python - это C-код, скомпилированный как C-код.Возможно, это источник проблемы?

0 голосов
/ 15 марта 2018

Приведенный ниже код выполнит модуль test.py.Python будет искать модуль в наборе путей.Таким образом, путь должен быть обработан в первую очередь.

Py_Initialize();

string path = "Python Scripts/";

//Set the path
PyRun_SimpleString("import sys");
string str = "sys.path.append('" + path + "')";
PyRun_SimpleString(str.c_str());

//Dont use test.py as it actually searches sub module test>>py
PyObject * moduleName = PyUnicode_FromString("test");
PyObject * pluginModule = PyImport_Import(moduleName);

if (pluginModule == nullptr)
{
    PyErr_Print();
    return "";
}

//Do the executions here

//clean up
Py_DECREF(moduleName);
Py_DECREF(pluginModule);
Py_DECREF(transformFunc);
Py_DECREF(result);

Py_Finalize();
0 голосов
/ 06 ноября 2015

А как насчет этого решения:

Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("execfile(\"ex30.py\")");
Py_Finalize();

Где ex30.py это имя скрипта Python, который я запускаю.

0 голосов
/ 03 июня 2014

Если вы построили свой тест с VC 2010, у вас наверняка будут проблемы - VC9 (VS 2008) и VC10 (VS 2010) имеют взаимно несовместимые библиотеки поддержки DLL, которые обычно требуются (реализуйте printf, файловый ввод-вывод и тому подобное). вещь). Вы не можете смешивать их, если они включают стандартные библиотеки, что делает сборка Python.

У вас всегда есть возможность использовать gcc (например, Cygwin или mingw) или загрузить Visual Studio 2008 Express, что должно хорошо работать для экспериментов по внедрению Python. Я использовал оба со стандартной сборкой Python 2.7.6.

...