使用Python.h从C ++调用Django

时间:2013-06-11 09:11:17

标签: c++ python c django python-2.7

我需要从C ++调用Django函数并在我的C ++代码中获取它们的输出。 如您所知,Django的使用方法是调用Manage.py Python脚本,将所需函数作为第一个参数和参数。

现在我有一个名为“test”的测试函数,它返回一个JSON格式的字符串。

因此,如果我打电话:

    python manage.py test

我得到以下内容:

   {'products': [{'id': 125, 'label': 'Robin'}, {'id': 4, 'label': 'Robinou'}]}

为了在cpp中得到这个,我可以:

   system(python path.../manage.py test);

并抓住输出。但我不喜欢它。我也可以使用Boost.Python。我也不喜欢它。

我希望能够仅在C ++ / Python.h中执行此操作,以便考虑大小和速度。

这是我正在运行的manage.py:

   import os
   import sys

   sys.path.append('C:\ds')

   if __name__ == "__main__":
       os.environ.setdefault("DJANGO_SETTINGS_MODULE", "frontoffice.settings")

   from django.core.management import execute_from_command_line
   execute_from_command_line(sys.argv)

如果我添加 print sys.argv ,我会收到以下输出: ['manage.py', 'test']

所以我设法以令人讨厌的方式做到了:

   bool initPython()
   {
       Py_Initialize();

       int check = 0;

       check = PyRun_SimpleString("import sys");
       check = PyRun_SimpleString("import os");
       check = PyRun_SimpleString("sys.path.append('C:\\ds')");
       check = PyRun_SimpleString("os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"frontoffice.settings\")");
       check = PyRun_SimpleString("from django.core.management import execute_from_command_line");

       if(check == 0) return true;
       else return false;
   }

   std::string execPythonCommand(std::string cmd)
   {
       std::string command = std::string("robin = ['dontreallycarewhatitis',       '").append(cmd).append("']");

       PyRun_SimpleString(command.c_str());
       PyRun_SimpleString("execute_from_command_line(robin)");
   }

没什么特别的。具有跨平台的优势但是捕获输出是一团糟,所以它可以工作,但它不是我想要的。我希望能够直接获取execute_from_comand_line命令的输出。

到目前为止,我已经提出了这个问题。运行initPython()之后:

    PyObject* executeCmd = PyImport_Import(PyString_FromString("django.core.management"));
    PyObject* executeFunc = PyObject_GetAttrString(executeCmd, "execute_from_command_line");

    std::cout << "Imported function." << " isNULL: " << (executeFunc == NULL) << " isExecutable: " << PyCallable_Check((executeFunc)) << std::endl;

所以我设法获得了execute_from_command_line函数的Cpp对象 - 它是可调用的。这是它变得棘手的地方。我怎么称呼它?

根据Python文档,

sys.argv是一个列表。所以我尝试重新创建完全相同的东西并调用它:

    PyObject* pRobin = PyList_New(2);
    PyObject* pString = PyString_FromString("test");
    PyObject* pString0 = PyString_FromString("manage.py");
    PyList_Append(pRobin,pString0);
    PyList_Append(pRobin,pString);

    PyObject* pValue = PyObject_CallObject(executeFunc, pRobin);
    //PyObject* pValue = PyObject_CallFunctionObjArgs(executeFunc, pRobin, NULL); //Doesn't work either

现在我已经尝试了一切。 PyObject_CallObject,CallFunction,CallFunctionObjArgs,使用Tuple而不是List,而PyErr_Print()并没有给我任何明确的信息。我真的不是Python专家,我正在努力解决这个问题。如何让pValue存储测试例程的输出JSON字符串?

供参考:

    >>> inspect.getargspec(django.core.management.execute_from_command_line)
    ArgSpec(args=['argv'], varargs=None, keywords=None, defaults=(None,))

我需要经常快速地运行manage.py xxx(其中xxx是一个命令),所以我真的想使用C / API而不是做一些令人讨厌的stdio捕获。

仅供参考我在后面使用VS2012,Windows 8,Python 2.7和PostGRE。 任何和所有的想法将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:2)

我对从C ++调用Python一无所知,但在Python中动态调用管理命令的方法是使用django.core.management.call_command。使用它可能会让事情变得更容易。