Note that there are some explanatory texts on larger screens.

plurals
  1. POCalling Django from C++ using Python.h
    text
    copied!<p>I need to call Django functions from C++ and get their output in my C++ code. As you know, Django is used by calling the Manage.py Python script with the wanted function as first parameter and arguments after.</p> <p>Right now I have a test function, named "test", that returns a JSON-formatted string. </p> <p>Therefore if I call:</p> <pre><code> python manage.py test </code></pre> <p>I get the following :</p> <pre><code> {'products': [{'id': 125, 'label': 'Robin'}, {'id': 4, 'label': 'Robinou'}]} </code></pre> <p>To get this in cpp I can:</p> <pre><code> system(python path.../manage.py test); </code></pre> <p>and catch the output. But I don't like it. I could also use Boost.Python. I don't like it either.</p> <p>I want to be able to do this in C++/Python.h only, for size and speed considerations.</p> <p>This is the manage.py I am running:</p> <pre><code> 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) </code></pre> <p>If I add a <em><code>print sys.argv</code></em> I get the following output: <em><code>['manage.py', 'test']</code></em> .</p> <p>So I managed to do it in a <strong>nasty</strong> way:</p> <pre><code> 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)"); } </code></pre> <p>Nothing fancy. Has the advantage of being cross platform but catching the output is a mess, so it works but it's not what I am looking for. I would like to be able to directly get the output of the execute_from_comand_line command.</p> <p>Here is what I've come up with so far. After running initPython(): </p> <pre><code> PyObject* executeCmd = PyImport_Import(PyString_FromString("django.core.management")); PyObject* executeFunc = PyObject_GetAttrString(executeCmd, "execute_from_command_line"); std::cout &lt;&lt; "Imported function." &lt;&lt; " isNULL: " &lt;&lt; (executeFunc == NULL) &lt;&lt; " isExecutable: " &lt;&lt; PyCallable_Check((executeFunc)) &lt;&lt; std::endl; </code></pre> <p>So I managed to get a Cpp Object of the execute_from_command_line function - and it is callable. Here is where it gets tricky. How do I call it?</p> <p>sys.argv, according to the Python Documentation, is a list. So I tried recreating the exact same thing and calling it:</p> <pre><code> 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 </code></pre> <p>Now I've tried everything. PyObject_CallObject, CallFunction, CallFunctionObjArgs, using a Tuple instead of a List, and PyErr_Print() isn't giving me anything explicit. I'm really not a Python expert and am struggling with this issue. How can I get pValue to store the output JSON string of the test routine?</p> <p>FYI:</p> <pre><code> &gt;&gt;&gt; inspect.getargspec(django.core.management.execute_from_command_line) ArgSpec(args=['argv'], varargs=None, keywords=None, defaults=(None,)) </code></pre> <p>In time I will need to run manage.py xxx (where xxx is a command) frequently and quickly, so I would really like to use the C/API rather than do some nasty stdio catching. </p> <p>FYI I'm on VS2012, Windows 8, Python 2.7, and PostGRE in the back. Any and all ideas would be greatly appreciated. Thanks!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload