与Python代码原型编译之前(Prototyping with Python code befor

2019-08-31 10:01发布

我一直在思索写峰拟合库一会儿。 我知道Python的相当好,并计划实现在Python一切开始,但设想,我可能最终重新实现在编译语言一些核心例程。

IIRC,Python的原职权范围之一是作为原型语言,但是Python是在允许功能,函子,对象传递给函数和方法相当宽松,而我怀疑同样是不属实的说C或Fortran语言。

我应该知道的关于设计功能/班,我设想将不得不接口送入编译语言? 又有多少这些潜在的问题是由库,如ctypes的,BGEN,处理SWIG , Boost.Python的 , 用Cython或Python的SIP ?

对于这个特定的使用情况中,(一个配件库)我想允许用户定义的数学函数(高斯,洛伦兹等),其然后可以由编译代码嵌合库传递一种解释Python函数。 传递和返回数组也是必不可少的。

Answer 1:

最后,我真的可以把一个值答案:)问题。

我已经调查f2py,Boost.Python的,痛饮,用Cython和高硼硅对我的工作(在光学测量技术博士)。 我用痛饮广泛,Boost.Python的一些和耐热玻璃,并用Cython了很多。 我也用ctypes的。 这是我的明细:

免责声明 :这是我个人的经验。 我没有参与任何与这些项目。

痛饮:不使用C ++发挥出色。 它应该,但名称重整在链接步骤的问题是一个大难题,我在Linux和Mac OS X.如果你有C代码,并希望它接口到蟒蛇,它是一个很好的解决方案。 我裹GTS我的需求,并从根本上写,我可以连接到一个C共享库需要。 我不会推荐它。

ctypes的:我写了使用ctypes的一个libdc1394(IEEE相机库)的包装,这是一个非常straigtforward经验。 你可以找到的代码https://launchpad.net/pydc1394 。 这是一个大量的工作头转换成Python代码,但随后的一切工作可靠。 这是一个很好的方式,如果你想接口的外部库。 ctypes的也是蟒STDLIB,所以每个人都可以使用你的代码的时候了。 这也是与蟒蛇一个新的lib迅速玩耍的好方法。 我可以把它推荐给接入外部库。

Boost.Python的 :非常愉快。 如果你已经有了自己的C ++代码要在Python中使用,去为这一点。 这是很容易的C ++类结构,这种方式转化为Python类结构。 我建议,如果你有C设定在python需要++代码。

耐热玻璃/用Cython:使用用Cython,不耐热玻璃。 期。 用Cython更先进,更愉快的使用。 现在,我做的一切用Cython,我使用SWIG或ctypes的做。 这也是如果你有运行速度太慢Python代码的最佳方式。 这个过程是绝对精彩:您转换您的Python模块到模块用Cython,建立他们,使分析和优化像它仍然是蟒蛇(无需工具的变化)。 然后,您可以申请使用Python代码混合尽可能多(或尽可能少)C代码。 这是远远快则不必重写用C应用程序的整个部分; 你只改写内部循环。

时序 :ctypes的具有最高的调用开销(〜700ns),其次是Boost.Python的(322ns),然后直接痛饮(290ns)。 用Cython具有最低的调用开销(124ns),并在那里花时间上最好的回馈(CPROFILE支持!)。 这些数字是从我的箱子调用返回从交互shell整数平凡函数; 因此,模块的进口开销不定时的,只有函数调用的开销。 因此,最简单,最有成效的通过分析和使用用Cython快速获取Python代码。

总结 :对于您的问题,请用Cython)。 我希望这将破败对某些人有用。 我会很乐意回答任何剩下的问题。


编辑 :我忘了提:为数值的目的(即连接到NumPy的)使用用Cython; 他们有这方面的支持(因为他们基本上都为此而开发用Cython)。 因此,这应该是你的决定另一个+1。



Answer 2:

我没有用痛饮或SIP,但我觉得写Python包装用Boost.Python的是非常强大的,比较容易使用。

我不是对你的要求是什么,通过C / C ++和Python之间类型的透明,但你可以做到这一点很容易要么露出C ++类型蟒蛇,或通过使用通用的boost ::蟒蛇::对象参数传送给C ++ API。 您也可以注册转换器自动转换蟒蛇类型C ++类型,反之亦然。

如果你打算使用Boost.Python的,该教程是一个良好的开端。

我已经实现有点类似于你所需要的东西。 我有一个接受一个Python功能和图像作为参数,和Python函数应用于图像中的每个像素中的C ++函数。

Image* unary(boost::python::object op, Image& im)
{
    Image* out = new Image(im.width(), im.height(), im.channels());
    for(unsigned int i=0; i<im.size(); i++)
    {
        (*out)[i] == extract<float>(op(im[i]));
    }
    return out;
}

在这种情况下,图像是一个C ++暴露于蟒(与浮子像素的图像)对象,并且op是一个Python定义函数(或真与__call__属性的任何蟒对象)。 然后,可以使用此函数如下(假设一元位于也包含图片和负载功能的称为图像中):

import image
im = image.load('somefile.tiff')
double_im = image.unary(lambda x: 2.0*x, im)

至于使用数组与提升,我个人还没有这样做,但我知道揭露阵列使用boost是Python可以使用的功能- 这可能是有益的。



Answer 3:

一种用于最终过渡到已编译代码计划的最佳方式是写在一个性能敏感部分作为简单功能的模块功能的风格 (无状态且无副作用),其接受并返回基本数据类型。

这将提供一个一对一的映射在你的Python原型代码最终编译代码,并让您使用ctypes的方便,避免了一大堆麻烦。

对于峰拟合,你几乎肯定会需要使用数组,这将事情复杂化了一点,但仍然是非常可行的与ctypes的。

如果你真的想使用更复杂的数据结构,或修改传递的参数, SWIG或Python的标准C的扩展接口,让你做你想要的,但麻烦的一些量。

对于你在做什么,你可能也想看看NumPy的 ,这可能会做一些你想推到C,以及提供工作在移动数据来回Python和C之间的一些额外的帮助 。



Answer 4:

f2py (部分numpy )是一个简单的替代SWIG和Boost.Python的用于包裹C / Fortran的数字运算代码。



Answer 5:

在我的经验中,有两种简单的方法来调入Python代码C代码。 还有其它的方法,所有这些都更恼人的和/或冗长。

第一和最容易的是编译一堆C代码作为一个单独的共享库,然后使用ctypes的调用的函数在该库中。 不幸的是,传递以外的任何其他基本数据类型是不平凡的。

第二最简单的方法是用C来写一个Python模块,然后调用函数模块中。 你可以通过你想这些C函数任何东西而不必通过任何箍跳。 而且很容易调用Python函数或方法从这些C函数,如下所述: https://docs.python.org/extending/extending.html#calling-python-functions-from-c

我没有跟夜风足够的经验,提供智能的评论。 虽然有可能通过ctypes的做事像通定制Python对象到C函数,或在C中定义新的Python类,这些东西是烦人的和详细的。我建议采取上述两种方法之一。



Answer 6:

Python是在允许功能,函子,对象传递给函数和方法相当宽松,而我怀疑同样是不属实的说C或Fortran语言。

在C你不能将一个函数作为参数传递给函数,但是你可以通过一个函数指针,也是同样不错的功能。

我不知道有多少,这将有助于当你试图整合C和Python代码,但我只是想澄清一个误解。



Answer 7:

除了上述的工具,我可以推荐使用的Pyrex (用于创建Python扩展模块)或Psyco的 (如JIT编译器为Python)。



文章来源: Prototyping with Python code before compiling