我正在使用C++中的一个嵌入式Python应用程序,使用Boosi::Python。嵌入式环境将自身的一部分导出为模块,换句话说,在环境中运行的python代码不会在标准python env中运行,因为无法导入嵌入式模块。
调试shell将是真正有助于调试的特性之一,在这里我可以分解并手动输入标准的python表达式来检查/修改当前状态。我遇到的问题是,我不能/不能提前知道是eval(如“2+2”)还是exec(如“a=2+2”)。如果exec(“2+2”)没有得到结果,如果eval(“a=2+2”)得到语法错误。(来自C背景,我不太明白为什么存在这种区别)。首先尝试eval,然后如果失败就执行,似乎是一个非常可疑的解决方案,尤其是因为副作用。
这里有一个MCVE,在这里我需要在eval和exec之间进行选择(obv.需要python dev和boost_python libs)
// g++ $(python3-config --cflags) so.cpp -fPIC -lboost_python3 $(python3-config --ldflags)
#include <boost/python.hpp>
#include <string>
#include <iostream>
namespace py = boost::python;
std::string pyobject_to_string(PyObject* obj)
{
PyObject* repr = PyObject_Str(obj);
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
const char *bytes = PyBytes_AS_STRING(str);
Py_XDECREF(repr);
Py_XDECREF(str);
return std::string(bytes);
}
int main(int argc, const char** argv)
{
// Init python env
Py_Initialize();
if (argc < 2)
{
return 1;
}
try
{
// TODO decide, based on argv[1], which needs to be called, this:
py::object res = py::eval(argv[1]);
std::cout << pyobject_to_string(res.ptr()) << std::endl;
// or this:
py::exec(argv[1]);
// or something else entirely...?
}
catch(py::error_already_set&)
{
if (PyErr_Occurred())
{
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
std::string message = pyobject_to_string(type) + ":" + pyobject_to_string(value);
//PyErr_Restore(type, value, traceback);
std::cerr << message << std::endl;
}
else
{
std::cerr << "unknown error" << std::endl;
return 1;
}
}
}
示例输出为:
$ ./a.out 2+2
4
$ ./a.out a=2+2
<class 'SyntaxError'>:('invalid syntax', ('<string>', 1, 2, 'a=2+2'))
多谢提前