Как импорт работает с Boost.Python из файлов Python - PullRequest
7 голосов
/ 15 февраля 2012

Я использую Boost.Python для встраивания интерпретатора в мой исполняемый файл C ++ и выполнения некоторых заранее написанных сценариев.У меня все работает так, что я могу вызывать функции в файле python, но код python, который я хочу использовать, импортирует внешние файлы, и этот импорт завершается ошибкой, потому что «модуль не назван».Если я запускаю скрипт напрямую из python, все работает, как и ожидалось.

Поэтому мой вопрос заключается в том, как правильно импортировать модули в скриптах Python, которые запускаются через привязки C ++?

Код C ++:

#include "boost/python.hpp"

int main(int argc, char** argv)
{
  try
  {
    Py_Initialize();
    boost::python::object test = boost::python::import("__main__");
    boost::python::object testDict = test.attr("__dict__");
    boost::python::exec_file("test.py", testDict, testDict);

  }
  catch(boost::python::error_already_set& e)
  {
    PyErr_Print();
  }
return 0;

}

Код Python:

import ModuleX

1 Ответ

14 голосов
/ 15 февраля 2012

Так что получается, что моя проблема - это простой случай, когда путь поиска модуля не был правильно задан при инициализации из C ++.

Из вступления к документации по Python:

В большинстве систем (в частности, в Unix и Windows, хотя детали немного разные), Py_Initialize () вычисляет модуль путь поиска, основанный на его наилучшем предположении о местонахождении стандарта Исполняемый файл интерпретатора Python, при условии, что библиотека Python находится в фиксированном месте относительно интерпретатора Python исполняемый файл. В частности, он ищет каталог с именем lib / pythonX.Y относительно родительского каталога, где исполняемый файл именованный python находится в пути поиска команд оболочки ( переменная окружения PATH).

Итак, это означает, что путь поиска модуля никоим образом не указывает на текущий рабочий каталог, скорее он указывает на папку установки системного python.

Решением для меня было правильно задать путь поиска модуля, чтобы он указывал на текущий рабочий каталог. Для этого вам нужно инициализировать python, а затем извлечь значение sys.path и добавить любые дополнительные пути. Извините за использование поддержки, если вы не в этом; Вы должны легко увидеть, как заменить любую желаемую строку.

Py_Initialize();

// now time to insert the current working directory into the python path so module search can take advantage
// this must happen after python has been initialised
boost::filesystem::path workingDir = boost::filesystem::absolute("./").normalize();
PyObject* sysPath = PySys_GetObject("path");
PyList_Insert( sysPath, 0, PyString_FromString(workingDir.string().c_str()));
...