在组件式GIS开发中集成Python方法研究

** 在组件式 GIS 开发中集成 Python 方法研究 **

马维峰 李林 王晓蕊

** 摘 ** ** 要 ** :可以通过在组件式 GIS 开发中集成 Python 来提高开发效率和质量。 Python 可以在 GIS 系统开发中编写数据的导入导出、处理、分析等模块,以及应用系统的业务逻辑层和科学研究中的空间分析、地学建模等模块。 Python 和组件式 GIS 可以通过 PythonCOM 实现的 Python 的 COM 接口来集成,在 VB 等开发语言中调用使用 Python 开发的 COM 服务器组件,从而实现了 GIS 系统和 Python 扩展的独立开发,无缝集成。

** 关键词 ** :组件式 GIS , Python , COM

1. 引言

随着计算机和地理信息技术的飞速发展, GIS 理论与应用的逐渐成熟,组件式技术已逐渐成为 GIS 软件的主流,改变了传统集成式 GIS 平台的工作模式,更适合用户进行二次开发以及与 MIS 、 OA 等其它系统的有机集成(宋关福, 1998 ;丁新, 2003 ;冯克忠, 2003 )。代表性的组件式 GIS 有 ERSI 的 ArcGIS 和北京超图的 SuperMap Object 。 SuperMap Object 是由北京超图公司和中科院地理与资源所所开发研制的新一代大型组件式地理信息系统平台。

由于大多数的脚本语言具有语法简单,易于学习,解释性、无需编译,易于部署和维护等优点,与直接使用静态编程语言 C 、 C++ 、 VB 等语言相比,使用动态脚本语言开发效率更高,开发和维护难度较低,作为系统扩展和快速开发语言具有一般静态编程语言不具有的优势。通过脚本语言扩展或集成已有系统,在很多软件平台中得到了广泛应用。在 ArcGIS 、 SuperMap Object 等基于 COM 的组件式地理信息系统平台中,可以通过 Python 等支持 COM 的脚本语言对系统进行功能扩展,集成其他程序,编写数据的导入导出、处理、分析等模块,特别是在应用系统开发的业务逻辑层(中间层)和科学研究中的空间分析、地学建模等方面更具优势。

Python 是一门解释性、面向对象、动态语义特征的高层语言( Lutz , 2001 )。 Python 具有高层的内建数据结构,动态类型和动态绑定,丰富的标准和第三方扩展库(包括科学计算、统计分析、可视化等模块),简单而易于阅读的语法,使其非常适合作快速应用开发来开发新系统、扩展已有系统,或作为胶水语言来连接、集成已有部件。有关 Python 的信息和语法等请参考 Python 官方网站( http://www.python.org )。

本文将介绍如何将介绍应用 Python 来扩展 SuperMap Object 等组件式 GIS 的思路、方法和优势。

2. 应用 Python 来扩展组件式 GIS

2.1. Python 的集成方式

在一般的编程语言中,集成或调用 Python 有以下几种方式:( 1 )在 C 或 C++ 语言中,可以利用 Python 提供的接口,调用 Python 的特定功能( Rossum , 2003 );( 2 )通过数据文件方式,通过操作系统的管道方式,直接调用 Python 执行环境和功能模块完成特定功能;( 3 )在 Windows 环境下,可以使用 PythonCOM 扩展模块将 Python 编写的对象包装成 COM 对象,供支持 COM 的编程语言调用( Hammond , 2000 )。其中( 1 )和( 3 )种方法为“无缝”集成,方法( 2 )为松散集成。

本文将通过 PythonCOM 扩展模块来完成与 SuperMap Object 相互调用。 PythonCOM 是由 ActiveState 公司开发的一个 Python 与 COM 、 ASP 集成的扩展模块,有关 PythonCOM 的信息请参考 ActiveState 公司网站( http://www.activestate.com )。以下将详细介绍如何创建一个可以被其他编程语言调用的 Python 模块,以及此模块如何与 SuperMap Object 交互完成特定的任务。

2.2. 应用 Python 实现 COM 对象

使用 Python 实现一个 COM 对象首先需要定义一个 Python 类,实现需要的属性和方法;其次需要应用 PythonCOM 扩展,实现 ProgID, CLSID 等属性,在注册表里注册这个 Python 类,使其成为一个可以被调用的 COM 对象。下面将通过一个简单的例子来说明这个过程。

我们来设计一个可以计算用户表达式的 COM 对象,以下是代码:

SimpleEVAL.py – 表达式求解

class PythonEVAL:

public_methods = [ 'MyEval' ]

reg_progid = "PythonGISDemos.EVAL"

Guid of this COM Searver

reg_clsid = "{6288B5B7 -870F -494E-A 4F 0-99868729804E}"

def MyEval(self, source, my_x):

x = my_x

return eval(source)

自注册部分

if name=='main':

print "Registering COM server..."

import win32com.server.register

win32com.server.register.UseCommandLine(PythonEVAL)


图 1 Python 编写的一个简单的 COM 对象的代码

以上的文件定义有 3 个特殊的属性字段,分别是:

public_methods

可以被调用的方法列表,本代码只有一个方法“ MyEval ”。

reg_progid

对象的名称,用来调用这个对象时使用。

reg_clsid

COM 对象的 CLSID ,可以使用“ pythoncom.CreateGuid() ”这个方法来生成,也可以使用别的工具。

MyEval 为我们定义的方法,参数为一个含“ x ”的表达式(字符串),和 x 的具体值,然后调用这个方法,返回计算后的值。后面的部分为自注册模块,如果是在 Python 的交互环境下直接调用此模块,则运行这段代码。将这个文件保存在“ Python23\Lib\site-packages ”这个目录下,首先运行一次,使其在注册表里注册这个 COM 组件。

这个对象可以应用在某些需要用户给出具体的表达式的进行分析计算的模块中。在编写这个类的过程中,你可以在 Python 的交互环境下边编写边测试,有助于验证算法和逻辑的正确性,保证开发效率和质量。

Python 开发的 COM 对象也可以通过命令行进行注册和反注册。注册一个对象:“ Python.exe YourServer.py ”;反注册一个对象:“ Python.exe YourServer.py –unregister ”。需要说明的是这个对象一定要有以上程序的注册部分这一段代码。

PythonCOM 还定义了除了“ public_methods ”以外其他一些特殊的属性字段,可以描述 COM 对象的其他特性。在代码中,还可以通过“ raise COMException("the error info") ”这样的语句来进行错误处理。对于使用 Python 创建 COM 对象的其他细节问题请参考 PythonCOM 相关文档。

2.3. 调用 Python 实现的 COM 对象

调用 Python 编写的 COM 对象和调用其他 COM 对象方法一样,以下将通过 VB 代码来实例说明其调用方法。

在 VB 中新建一个工程,在缺省窗体上放置 3 个文本框和一个按钮,在 Form 的 Load 事件里编写对 COM 对象的初始化代码,在按钮点击事件里,编写 COM 对象调用的代码,在 Form 的 Unload 事件里,销毁这个对象。全部代码见图 2 。

Public myServer As Object

Private Sub Command1_Click()

Text3.Text=myServer.MyEval(Text1.Text,Int(Text2.Text))

End Sub

Private Sub Form_Load()

Set myServer = CreateObject("PythonGISDemos.EVAL")

End Sub

Private Sub Form_Unload(Cancel As Integer)

Set myServer = Nothing

End Sub


图 2 VB 中调用 Python 编写的 COM 对象的代码

整个代码和调用其他 COM 对象没有什么差别。以下是程序运行的界面,对 x=2 ,表达式为“ 3x – xx ”进行求解,结果是 2 。

图 3 VB 中调用 Python 编写的 COM 对象的运行结果

我们可以把这段代码插入使用 SuperMap Object 等组件式 GIS ,开发语言为 VB 或其他语言的开发项目中需要用户给出具体的表达式的进行分析计算的模块中。需要说明的是,对于参数传递,数据类型,对象调用等使用 COM 开发需要注意的问题,在这里一样需要注意。另外有两个问题需要注意,第一,对于 VB 开发环境, VB 是大小写不敏感的,而 Python 是区分大小写的;第二是 Unicode 的问题, COM 传递的字符串都是 Unicode ,在 Python 中处理使用之前要根据需要转换为 Python 的字符串。

3. 应用实例

下面将使用 Python 来实现一个最小二乘拟合的模块。以下是代码:

LeastSq.py – 最小二乘拟合

from scipy import *

from scipy.optimize import leastsq

class PythonSq:

public_methods = ['AddX','AddY','leastsq','GetP']

reg_progid = "PythonGISDemos.LeastSq"

Guid of this COM Searver

reg_clsid = "{6278B5B7 -870F -494E-A 4F 0-92368724804E}"

程序中需要拟合的 X 和 Y 的值

x=[]

y=[]

输入 X 和 Y 的值,由于一般语言没有对应的序列等数据结构,所以逐个输入

def AddX(self, xx):

self.x.append(xx)

def AddY(self, yy):

self.y.append(yy)

求解剩余变量

def residuals(self, p, y, x):

a, b, c = p

y = array(y) # 将序列转换为矩阵

x = array(x)

err = y - (axx + b*x + c)

return err

求解参数

def leastsq(self):

<


Published At
Categories with Web编程
Tagged with
comments powered by Disqus