为似乎是编译时问题提升python运行时错误 - 如何影响性能?

时间:2013-07-17 02:46:22

标签: python boost enums boost-python

使用boost python,我在我的python包装器中添加了一个属性,其值来自枚举类型,例如:

scope().attr("myconstant")=some_namespace::some_class::some_enum_value;

但是当我导入我的python模块时出现运行时错误:

terminate called after throwing an instance of 'boost::python::error_already_set'

在其他线程之后,我将上面的内容放在try / catch中但是没有捕到任何东西来调用PyErr_Fetch。我仍然好奇原始python错误发生的地方。

事实证明我必须做

scope().attr("myconstant")=int(some_namespace::some_class::some_enum_value);

然后它运行。

另一个,但我认为相关的问题是,如果你在python包装器中导出一个返回C ++枚举的C ++函数,但是你没有导出那个枚举,一切都没问题,直到你从python调用这个函数。然后boost会生成一个关于未找到类型的python异常。

很明显,在运行时做一些事情似乎(对我来说)应该在编译时完成。这两个问题都很难诊断。有谁知道发生了什么?随着运行时发生的事情越来越多,我预计,如果我直接使用python扩展API,我是否会遇到boost python的性能问题?除了性能之外,我还担心提升python代码会有更多的错误,直到运行时才能找到,直到python扩展代码才会有。

另一方面,所有这些动态类型绑定是否有一些大的收获?很明显,有一个很好的boost接口用于编写我自己的python扩展 - 但是所有这些动态绑定是否更容易将新的boost python包装器添加到现有系统中,然后使用python扩展API直接编写包装器?

1 个答案:

答案 0 :(得分:1)

使用Python支持动态名称解析,我认为用Boost.python强制编译时断言是相当困难的。 C ++代码在运行时向Python公开,Boost.Python类型转换可能已在不同的模块中注册,在运行时单独加载。

Boost.Python,甚至是Python C-API,在运行时执行大部分工作。 Boost.Python不会将错误延迟到运行时,而不是Python C-API。当Python导入Boost.Python模块时,BOOST_PYTHON_MODULE代码执行,创建类型,注册类型标识,并注册允许Python和C ++对象之间无缝互操作的函数。总的来说,C-API或任何其他Python语言绑定工具集仍然需要相同的设置过程。由于Boost.Python提供了一种高级通用解决方案,因此与为应用程序量身定制的手写绑定相比,它可能会更加臃肿。

我个人的经验是,使用Boost.Python扩展现有系统比直接编写Python C-API更容易。我必须编写明显更少的代码,从而减少错误,同时提高可读性和可维护性。例如,考虑官方Python Extending Simple Example

#include <stdlib.h> // system
#include <Python.h>

static PyObject*
spam_system(PyObject* self, PyObject* args)
{
  const char* command;
  if (!PyArg_ParseTuple(args, "s", &command))
    return NULL;
  return Py_BuildValue("i", system(command));
}

static PyMethodDef SpamMethods[] =
{
  {"system", &spam_system, METH_VARARGS,
   "Execute a shell command."},
  {NULL, NULL, 0, NULL} /* Sentinel */
};

PyMODINIT_FUNC
initspam(void)
{
  Py_InitModule("spam", SpamMethods);
}

和Boost.Python中的等价物:

#include <stdlib.h> // system
#include <boost/python.hpp>

BOOST_PYTHON_MODULE(spam)
{
  boost::python::def("system", &system);
}