代码之家  ›  专栏  ›  技术社区  ›  virgesmith

嵌入式环境中的Python调试shell:exec还是eval?

  •  0
  • virgesmith  · 技术社区  · 6 年前

    我正在使用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'))
    

    多谢提前

    0 回复  |  直到 6 年前