python — неверный результат при использовании jinja2 в переполнении стека

Я использую этот код для шаблонов JSON с помощью Jinja2:

import json
from jinja2 import Template

def render_json(p_input_str, p_template_str, p_str):
p_input = json.loads(p_input_str)
t = Template(p_template_str)
return t.render(input=p_input, str=p_str)

temp.json:

{
"id" : "{{ input["id"] }}",
"data" : [
{% for item in input["list"] %}
{
"id" : "{{ item["id"] }}",
"value" : "{{ item["data"] }}"},
{% endfor %}
null
],
"str" : "{{ str }}",
"ext" : "{{ input["x"] }}"}

input.json:

{
"id" : "1",
"list" : [ { "id" : "2", "data" : "4" } ],
"x" : "20"}

с помощью python все работает нормально:

input_str=open("test.json").read()
template_str=open("temp.json").read()
print render_json(input_str, template_str, "1234")

выход:

{
"id" : "1",
"data" : [

{
"id" : "2",
"value" : "4"},

null
],
"str" : "1234",
"ext" : "20"}

но когда я пытаюсь позвонить render_json из с ++, input_str добавляется к выводу:

{
"id" : "1",
"list" : [ { "id" : "2", "data" : "4" } ],
"x" : "20"}
{
"id" : "1",
"data" : [

{
"id" : "2",
"value" : "4"},

null
],
"str" : "1234",
"ext" : "20"}

это мой код C ++ для встраивания Python:
это основано на документации Python Встраивание Python в другое приложение

int main(int argc, char *argv[])
{
std::stringstream buffer;
std::ifstream t;

t.open("test.json");
buffer << t.rdbuf();
std::string input_str = buffer.str();
t.close();
buffer.clear();

t.open("temp.json");
buffer << t.rdbuf();
std::string template_str = buffer.str();

std::vector<std::string> x = {input_str, template_str, "1234"};

PyObject *pName, *pModule, *pDict, *pFunc;
PyObject *pArgs, *pValue;

if (argc < 3)
{
printf("Usage: exe_name python_source function_name\n");
return 1;
}

Py_Initialize();
pName = PyString_FromString(argv[1]);
/* Error checking of pName left out */

pModule = PyImport_Import(pName);
Py_DECREF(pName);

if (pModule != NULL)
{
pFunc = PyObject_GetAttrString(pModule, argv[2]);
/* pFunc is a new reference */

if (pFunc && PyCallable_Check(pFunc))
{
pArgs = PyTuple_New(3);
for (int i = 0; i < 3; ++i)
{
pValue = PyString_FromString(x[i].c_str());
if (!pValue)
{
Py_DECREF(pArgs);
Py_DECREF(pModule);
fprintf(stderr, "Cannot convert argument\n");
return 1;
}
/* pValue reference stolen here: */
PyTuple_SetItem(pArgs, i, pValue);
}
pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
if (pValue != NULL)
{
printf("Result of call: %s\n", PyString_AsString(pValue));
Py_DECREF(pValue);
}
else
{
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr,"Call failed\n");
return 1;
}
}
else
{
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
}
Py_XDECREF(pFunc);
Py_DECREF(pModule);
}
else
{
PyErr_Print();
fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
return 1;
}
Py_Finalize();
return 0;
}

0

Решение

Уверен, это как-то связано с вашей конструкцией input_str а также template_str из того же std::stringstream и не имеет ничего общего с вашим питоном или привязками. То есть, если вы просто Распечатать template_str прежде чем позвонить вашему питону, вы увидите его уже содержит содержимое input_str в начале.

std::stringstream::clear не делает то, что вы думаете, это делает — это просто унаследовано от ios_base и это очищает флаги ошибок.

Просто используйте второй буфер. (или позвоните по телефону buffer.str("")который я считать делает то, что вы действительно хотите, но это, вероятно, не стоит снижения читабельности.)

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]