当前位置:  开发笔记 > 编程语言 > 正文

在编译之前使用Python代码进行原型设计

如何解决《在编译之前使用Python代码进行原型设计》经验,为你挑选了3个好方法。

我一直在考虑写一个峰值拟合库一段时间.我非常了解Python,并计划在Python中实现所有内容,但是设想我最终可能必须以编译语言重新实现一些核心例程.

IIRC,Python的原始版本之一是原型语言,但是Python在允许函数,仿函数,对象传递给函数和方法方面相当自由,而我怀疑C或Fortran也不是这样.

关于我设想的函数/类应该与编译语言接口,我应该知道些什么?这些潜在问题中有多少是由cTypes,bgen,SWIG,Boost.Python,Cython或Python SIP等库来处理的?

对于这个特殊的用例,(拟合库)我想让用户将数学函数(Guassian,Lorentzian等)定义为Python函数,然后可以通过编译的代码拟合库来解释它.传递和返回数组也很重要.



1> SirVer..:

最后一个问题,我真的可以给一个价值答案:).

我为我的工作调查了f2py,boost.python,swig,cython和pyrex(光学测量技术博士).我广泛使用swig,boost.python一些和pyrex和cython很多.我也用过ctypes.这是我的细分:

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

swig: 与c ++不兼容.它应该,但在链接步骤中命名错误问题是我在Linux和Mac OS X上的一个主要问题.如果你有C代码并希望它接口到python,这是一个很好的解决方案.我根据自己的需要包装了GTS,并且需要编写一个我可以连接的C共享库.我不推荐它.

Ctypes: 我用ctypes写了一个libdc1394(IEEE Camera库)包装器,这是一个非常简单的经验.您可以在https://launchpad.net/pydc1394上找到该代码.将头文件转换为python代码需要做很多工作,但一切都可靠.如果要连接外部库,这是一种很好的方法.Ctypes也在python的stdlib中,所以每个人都可以立即使用你的代码.这也是快速使用python中的新lib的好方法.我可以推荐它与外部库的接口.

Boost.Python:非常愉快.如果您已经拥有自己想要在python中使用的C++代码,那就去做吧.以这种方式将c ++类结构转换为python类结构非常容易.如果你有python中需要的c ++代码,我推荐它.

Pyrex/Cython:使用Cython,而不是Pyrex.期.Cython更先进,更有趣.如今,我用cython做了一切,我曾经用SWIG或Ctypes做过.如果你的python代码运行得太慢,这也是最好的方法.这个过程绝对是太棒了:你将你的python模块转换成cython模块,构建它们并保持分析和优化,就像它仍然是python(不需要更改工具).然后,您可以应用与python代码混合的尽可能多(或尽可能少)的C代码.这比使用C重写应用程序的整个部分要快得多; 你只重写了内循环.

计时:ctypes的呼叫开销最高(约700ns),其次是boost.python(322ns),然后是swig(290ns).Cython具有最低的呼叫开销(124ns)以及花费时间的最佳反馈(cProfile支持!).这些数字来自我的盒子,调用一个简单的函数,从交互式shell返回一个整数; 因此,模块导入开销不是定时的,只有函数调用开销.因此,通过分析和使用cython来快速获取python代码是最简单和最有效的.

简介:对于您的问题,请使用Cython;).我希望这个破坏对某些人有用.我很乐意回答任何剩下的问题.


编辑:我忘记提及:出于数字目的(即连接到NumPy)使用Cython; 他们支持它(因为他们基本上为此目的开发了cython).所以这应该是你决定的另一个+1.



2> Moe..:

我没有使用SWIG或SIP,但我发现用boost.python编写Python包装器非常强大且相对容易使用.

我不清楚你在C/C++和python之间传递类型的要求是什么,但你可以通过将C++类型暴露给python,或者通过使用通用的boost :: python :: object参数来轻松实现C++ API.您还可以注册转换器以自动将python类型转换为C++类型,反之亦然.

如果您计划使用boost.python,那么本教程是一个很好的起点.

我已经实现了一些类似于你需要的东西.我有一个C++函数接受python函数和图像作为参数,并将python函数应用于图像中的每个像素.

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

在这种情况下,Image是一个暴露给python的C++对象(一个带有float像素的图像),op是一个python定义的函数(或者实际上是一个带有__call__属性的python对象).然后,您可以按如下方式使用此函数(假设一元位于被调用的图像中,该图像还包含图像和加载函数):

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

至于使用带有boost的数组,我个人还没有这样做,但我知道使用boost将数组暴露给python的功能是可用的 - 这可能会有所帮助.



3> Jason Pratt..:

规划最终转换为已编译代码的最佳方法是将性能敏感部分编写为功能样式(无状态且无副作用)的简单函数模块,这些函数接受并返回基本数据类型.

这将提供从Python原型代码到最终编译代码的一对一映射,并且可以让您轻松使用ctypes并避免一大堆麻烦.

对于峰值拟合,你几乎肯定需要使用数组,这会使事情变得复杂,但仍然非常适合ctypes.

如果你真的想要使用更复杂的数据结构,或修改传递的参数,SWIG或Python的标准C-extension接口将让你做你想做的事情,但有一些麻烦.

对于你正在做的事情,你可能还想查看NumPy,它可能会做一些你想要推送到C的工作,以及提供一些在Python和C之间来回移动数据的额外帮助.

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有