Embedded Python应用小结

http://www.bloggogo.com/?cat=7
  Embedded Python应用小结
Thursday, January 24th, 2008

很久以前就想写一篇这方面的笔记,这次做一个客户端验的模块,服务器端是用C#写的DES3加密,还要用到Socket连接,实在不是一般的麻烦,懒人有懒办法,决定用Python脚本来实现这个功能,顺便翻出以前的代码。把问题总结一下。

总的说起来Python Embeded有几个步骤。

(1)初始化Python脚本运行环境

Py_Initialize();

(2) 脚本的编译

bytecode = Py_CompileString(script.c_str() , "active" , Py_file_input)

python有多种embeded的形式,我最喜欢的是用Py_CompileString来编译一个.py的脚本文件,这样有下面几个好处,引用方便,调试方便,灵活。

编译好后会返回一个PyObject* 的bytecode对象

要注意的是.py脚本的格式很重要,一定记得换行用Unix方式的,否则是不会编译通过的,我第一次时就找了很久才发现这个问题,还有一个要注意的问题是最好编一个调试版本的python的dll和库,这样便于发现问题。

(3)导入编译好的脚本

module=PyImport_ExecCodeModule("active",bytecode),这个过程是构造库的过程,运行完成之后就会把你要应用的Python库装入内存当中。

(4)从module中导出对象

dict = PyModule_GetDict( module )

导出对象表后你就可以按照你的需要使用你想用的python对象,这里常用的是类,方法,函数,我这里只用了最简单全局函数,用fun = PyDict_GetItemString( dict , "active" );得到想要使用的函数对象。

(5)调用Python函数

还剩下一个问题了,如何给调用的Python函数传递参数

python函数的参数是一个Tuple类型的值,通俗的理解就是名字和对象的列表,这样不管你传递多少参数,只要用一个Tuple类型就都解决了,代码如下

args = PyTuple_New( argsnum );
if( !args )
{
    PyErr_Print();
    assert(false);                                       
}   
for( i = 0 ; i < argsnum ; i++ )
{
    value = PyString_FromString( strings[i] );
    PyTuple_SetItem( args , i , value );
}


用PyString_FromString等类型转换函数就可以实现参数生成的过程了。

(6)调用函数,得到返回值

value = PyObject_CallObject( fun , args );
if(!value)
{
    PyErr_Print();
    assert(false);   
}

value是PyObject用转换函数就可以得到C++类型的返回值了,到这儿一个完整的调用过程就结束了

(7)其它

调用结束后释放脚本运行环境Py_Finalize();

注意下面几个问题,PyObject*都是有引用计数的,看文档说明有些对象是要自己处理引用计数的用Py_DECREF来释放对象,一般说如是类new操作的对象都要释放对象,如果是通过query出来的对象一般不用释放。

时间有限,很多细节的东西没有办法写得很详细了,希望我的笔记能帮助做同样工作的程序员们。

 

 

BoostPython应用小结

Thursday, January 3rd, 2008

这 两天抽空用boost写了一个Python的扩展,主要用来验收收到的文件内容,结果发现了一个莫名其妙的错误,主要是在调用扩展函数的时候,在析构调用 参数的时候会报一个错误,是释放堆内存时的一个异常,联想以前写程序时出现的问题,想到可能是因为我的扩展是一个动态库,这个动态库要依赖 boost_python的动态库,在释放内存时会出现问题,于是想到把boost_python编成静态库,然后静态链接解决这个问题。把 boost_python改成静态库后加到工程中发现很多符号找不到,仔细看错误,发现引入的符号还是以动态库符号的方式引用的,估计是宏定义不对,再打 开VC工程属性->Preprocessor->Preprocessor Definitions找到一个定义"BOOST_PYTHON_DYNAMIC_LIB"把这个改成 "BOOST_PYTHON_STATIC_LIB"重新编译,扩展工程也同样定义BOOST_PYTHON_STATIC_LIB重新编译,一切OK。 希望我的经验能帮助其它用boostpython开发的程序员们。

wxPython开发心得

Thursday, March 22nd, 2007

昨 天吃饭,老婆又中了50元,这是我们家小呼呼带给我们俩又一笔小财,我们家这个小金猪真有财运哈,高兴死我了…..我这两天终于把demo搞定了,说实话 还真是有点儿复杂,为了演示方便,想写一个类似xampp那样的控制台程序,这样就连老板也可以做演示,想了半天选定用wxPython做UI的设计,做 UI的过程中对python的界面开发也有了一些心得。

(一)wxPython的框架

这个用过MFC的都应该很清楚,一般显示一个窗口要创建一个基本的application类(从wx.App)用来做窗口主线程,用来处理 windows消息的,然后还要有一个主窗口,窗口类型根据你的需要选择不同的窗口类型,我选择的是wx.Frame,剩下的工作就是把wxDemo打 开,把你想用的代码C & P过来就行了,基本上你能想到的一般控件都可以在例子中找到。一般消息通过调用Bind函数可以很方便的实现消息回调。

(二)wxPython不足

仔细看了wxPython的例子发现没有提供一些特别的控件如视频编辑中的时间标尺的控件,不知道怎么实现自己定义的一些控件。

(三)其它补充

python中os.spawnl的说明,用这个命令打开一个子进程,我用这个函数实现打开外部URL的功能,发现一个问题,要指定全路径才可以, 这个不是很方便,不知道是不是有别的简单的方法,服务器的启动用wx.Process的包装类来实现,很方便,原来想把命令行输出重定向通过管道把服务器 输出重定向到我的Edit控件输出,发现会有死锁的现象,后来放弃了,真接到控制台吧,也挺方便的。

要是想做个工具什么的用wxPythong还是不错的选择,代码编写简单,而且还可以跨平台,不过要是做太复杂的界面还是不是很方便,我想到的解决方案就是用boost和c++为python做扩展,这个目前没有时间实现了看以后的吧。

Python编程Decorator

Monday, February 5th, 2007

Python 中在2.4中加入一种新的语法元素Decorator,从字面上讲这个语法元素是一个修饰符,在Dr.Dobb’s的文章中有这样一段描述” Decorators are Python objects that can register,annotate,and/or wrap a Python function or object”,个人理解就是对一个函数进行调用前做些额外的处理,有点像挂函数钩子,执行这个函数前先经过一个处理后再真正调用这个函数本身,这个语法 的出现最早也是为了方便的实现classmethod和staticmethod的调用。Deocrator在Python元编程里有很重要的作用,这方 面的概念跟Java中的反射很相似,下面的例子是说明Decorator的一个简单应用。

不用Decorator

class democlass:
def demomethod(cls,x,y):
print ‘class something : somemethod %d , %d’ % (x,y)
demomethod = classmethod(demomethod)

使用Decorator

class democlass:
@classmethod
def demomethod(cls,x,y):
print ‘class something : somemethod %d , %d’ % (x,y)

(一)Decorator应用之一:Trace 函数

这个是最普通的一个应用,使用Trace函数或一个Trace类可以知道一个函数的状态和参数,这个功能可以很方便的帮助你调试代码,了解当前的运 行情况,这里将用到下面几个知识点Function as Decorator、Object as Decorator、Decorator with arguments(参数)

1.Function Decorator

def traced(func):
def wrapper(*__args,**__kw):
print ‘entering’,func,__args,__kw
try:
return func(*__args,**__kw)
finally:
print ‘exiting’,func
return wrapper

2.Class Decorator

class traced:
def __init__(self,func):
self._func = func
def __call__(__self,*__args,**__kw):
print ‘entering’,__self._func
try:
return __self._func(*__args,**__kw)
finally:
print ‘exiting’,__self._func

@traced
def demofun(x,y):
print ‘call demofun’,x,y

if __name__ == ‘__main__’:

demofun(0,1)

======程序将有如下的输出======

entering
call demofun 0 1
exiting

3.Decorator with arguments

如果你想在trace的信息中加入一些其它的信息,比如说作者,日期什么的这时候可以按下面的代码提供这些信息

def traced(author_name):
def dec(func):
func._author_name = author_name
def wrapper(*__args,**__kw):
print ‘entering’,func,__args,func.__dict__
try:
return func(*__args,**__kw)
finally:
print ‘exiting’,func
return wrapper
return dec

你可能感兴趣的:(Embedded Python应用小结)