【转载】Python与ArcGIS Engine的集成
1 在Python中调用AO类库
1.1 准备工作
本文所使用环境:ArcGIS 10.0、Python 2.6。
AO类库在本质是COM组件,在Python中无法直接使用COM,应此需要把COM转换成Python能识别的类型。
Comtypes是一个开源的基于ctypes python的、轻量级的纯COM客户端和服务器框架,利用comtypes可以把AO对象转换成python能识别的类型。Comtypes的下载地址:http://sourceforge.net/projects/comtypes/。
下载完直接安装后就可以在Python中使用了。Comtypes是利用comtypes.client.GetModule方法将需要的类库生成到comtypes/gen文件夹中,因此 首先需要定义一个GetAoModule函数:
def GetAoModule(moduleName):
import comtypes
from comtypes.client import GetModule
GetModule('C:/Program Files/ArcGIS/Engine10.0/com/' + moduleName)
这样就可以引入AO对象库了,比如使用GetAoModule('esriControls.olb'),就可以引入esriControl了。
我们在使用AO时还需要创建AO对象,这里要使用 comtypes.client.CreateObjec来进行创建,在程序中定义一个AoObj函数:
#在Python中创建一个ArcObjects对象
def AoObj(MyClass, MyInterface):
from comtypes.client import CreateObject
try:
obj = CreateObject(MyClass, interface=MyInterface)
return obj
except:
return None
此外还需要定义一个函数用于接口跳转:
#接口跳转
def AoCType(obj, interface):
try:
newobj = obj.QueryInterface(interface)
return newobj
except:
return None
使用AO还需要绑定ArcGIS Engine或Desktop的许可。在ArcGIS 10.0之后,还需要指定ArcGIS的版本。
#利用GP绑定许可
import arcgisscripting
gp = arcgisscripting.create(10.0)
gp.setProduct("ArcEngine")
#初始化许可
GetAoModule('esriSystem.olb')
import comtypes.gen.esriSystem as esriSystem
pInit = AoObj(esriSystem.AoInitialize,esriSystem.IAoInitialize)
eProduct = esriSystem.esriLicenseProductCodeEngine
licenseStatus = pInit.IsProductCodeAvailable(eProduct)
if licenseStatus == esriSystem.esriLicenseAvailable:
pInit.Initialize(eProduct)
这样在python中使用AO的准备工作就完成了
1.2 编写脚本
Python作为一种脚本语言,能够执行批处理程序、开发基于ArcGIS Desktop的小工具,特别是在执行批处理程序上有着很明显的优势。本节利用python编写了一个脚本,用于输出线要素每个结点的M值。
具体代码如下:
|
#打开Shapefile GetAoModule('esriGeoDatabase.olb') import comtypes.gen.esriGeoDatabase as esriGeoDatabase GetAoModule('esriDataSourcesFile.olb') import comtypes.gen.esriDataSourcesFile as esriDataSourcesFile GetAoModule('esriDataSourcesGDB.olb') import comtypes.gen.esriDataSourcesGDB as esriDataSourcesGDB GetAoModule('esriGeometry.olb') import comtypes.gen.esriGeometry as esriGeometry fileWorkspaceFactory=AoObj(esriDataSourcesFile.ShapefileWorkspaceFactory,esriGeoDatabase.IWorkspaceFactory) pfw=fileWorkspaceFactory.OpenFromFile('D:/LinearReferencing/',0) featureWorkspce = AoCType(pfw, esriGeoDatabase.IFeatureWorkspace) featureClass=AoObj(esriGeoDatabase.FeatureClass,esriGeoDatabase.IFeatureClass) featureClass=featureWorkspce.OpenFeatureClass("Export_Output.shp") #选择所有要素 queryFilter2=AoObj(esriGeoDatabase.QueryFilter,esriGeoDatabase.IQueryFilter2) queryFilter2.WhereClause ='' fs=featureClass.Search(queryFilter2,0)#0就是Fasle featureCursor=AoCType(fs, esriGeoDatabase.IFeatureCursor) #创建txt f=open('D:/M值表.txt','w') fc = featureCursor.NextFeature() #循环输出每个线要素的所有结点的M值 while fc: pFeat = AoCType(fc, esriGeoDatabase.IFeature) ps=pFeat.Shape pPl=AoCType(ps, esriGeometry.IPolyline) pPC=AoCType(pPl, esriGeometry.IPointCollection) f.write('OBJECTID ' + ','+repr(pFeat.OID)+'\n') f.write('节点' + "," + ' M值'+'\n') for i in range(0,pPC.PointCount): ppct=pPC.Point[i] pPoint =AoCType(ppct, esriGeometry.IPoint) ID=i+1 f.write(repr(ID) + ", " + repr(pPoint.M)+'\n') fc = featureCursor.NextFeature() #关闭文件输入 f.close() |
脚本运行完毕后,会创建一个txt文件,里面包含了每条线要素所有结点的M值,如下图所示:
1.3 创建GUI程序
Python是一种脚本语言,但是python也有很多GUI程序包,比如tkinter、wxpython、pyqt等,利用这些程序包可以创建GUI应用程序。本小节利用wxpython调用AE控件创建了一个简单的应用程序,如下图所示。
首先必须引入esriControls.olb,这样才能使用MapControl、TOCControl等AE控件。
|
#引入esriControls GetAoModule('esriControls.olb') import comtypes.gen.esriControls as esriControls |
接下来利用wxPython建立框架,并引入MapControl、TOCControl和ToolbarControl。要注意的问题是必须把AE控件当成ActiveX进行转换,这样才能够在Python中应用。
|
import wx import wx.aui #把控件当成ActiveX进行转换 import wx.lib.activex as ActiveX class MyFrame(wx.Frame): def __init__(self, *args, **kwargs): wx.Frame.__init__(self, *args, **kwargs) self.mgr = wx.aui.AuiManager(self) #添加AE控件 ax_MapControl = ActiveX.ActiveXCtrl(self,str(esriControls.MapControl ._reg_clsid_), -1, wx.DefaultPosition,wx.DefaultSize, 0, "MapControl") ax_TocControl = ActiveX.ActiveXCtrl(self,str(esriControls.TOCControl ._reg_clsid_), -1, wx.DefaultPosition,wx.Size(200,100), 0, "TocControl") ax_ToolbarControl = ActiveX.ActiveXCtrl(self, str(esriControls.ToolbarControl._reg_clsid_), -1, wx.DefaultPosition,wx.DefaultSize, 0, "ToolbarControl") #把控件添加至Frame中 aui.AuiPaneInfo(). self.mgr.AddPane(ax_ToolbarControl, wx.aui.AuiPaneInfo().Name("地图工具条").Caption("地图工具条").Top()) self.mgr.AddPane(ax_MapControl, wx.aui.AuiPaneInfo().Name("地图控件").Caption("地图控件").Center()) self.mgr.AddPane(ax_TocControl, wx.aui.AuiPaneInfo().Name("TOC目录").Caption("TOC目录").Left()) #设置mapcontrol与 toolbarControl和tocControl的伙伴关系 toolbarControl = ax_ToolbarControl.ctrl tocControl = ax_TocControl.ctrl MapControl= ax_MapControl.GetCtrl() self.Add_toolbar_Command(toolbarControl) toolbarControl.SetBuddyControl(MapControl) tocControl.SetBuddyControl(MapControl) self.mgr.Update() #向 ToolbarControl 中添加命令按钮 def Add_toolbar_Command(self,toolbarControl): toolbarControl.AddItem('esriControlCommands.ControlsOpenDocCommand',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapZoomInTool',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapZoomOutTool',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapZoomInFixedCommand',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapZoomOutFixedCommand',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapPanTool',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapFullExtentCommand',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapZoomToLastExtentBackCommand',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsMapZoomToLastExtentForwardCommand',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsSelectFeaturesTool',-1,-1,False,0,1) toolbarControl.AddItem('esriControlCommands.ControlsSelectTool',-1,-1,False,0,1) class MyApp(wx.App): def OnInit(self): frame = MyFrame(None, -1, '在Python中使用ArcGIS Engine',(100,100),(800,600)) frame.Show() self.SetTopWindow(frame) return 1 app = MyApp(0) app.MainLoop() |
2 ArcGIS Engine程序中调用python脚本
基于AE的二次开发有很多种方式,包括JAVA、C++、.NET。本节介绍在.NET中调用python脚本。
在.NET程序中使用python脚本,必须使用IronPython。IronPython是一个开源的项目,能够使用户在.NET环境中使用python,我们可以在http://ironpython.codeplex.com/ 上下载对应用python版本的IronPython。最新的IronPython要求.NET版本必须在4.0以上。
下载并安装IronPython后,需要在.NET程序中进行设置。首先在程序中添加IronPython.dll和Microsoft.Scripting.dll的引用,这两个dll位于IronPython的安装目录下。

然后在程序中添加using IronPython.Hosting和using Microsoft.Scripting.Hosting。
我们还需要把python文件添加至工程中,需要注意的是,要把Python文件的属性“复制到输出目录”设置成“始终复制”。

这样,就可以在程序中调用python脚本了。
|
ScriptRuntime pyRuntime = Python.CreateRuntime(); dynamic obj = pyRuntime.UseFile("Ratio_divided.py"); obj.Ratio_divided(); |
需要注意的是Python脚本中不能使用ArcPy包,否则就会出现如下的错误:没有arcpy的模型包。

这样,就可以在程序中调用python脚本了。
|
ScriptRuntime pyRuntime = Python.CreateRuntime(); dynamic obj = pyRuntime.UseFile("Ratio_divided.py"); obj.Ratio_divided(); |
需要注意的是Python脚本中不能使用ArcPy包,否则就会出现如下的错误:没有arcpy的模型包。

这主要是因为IronPython不支持ArcPy,因为ArcPy是基于cpython开发的,而IronPython不支持cpython,当然国外也有人用IronClad(一个IronPython)在IronPython中使用cpython的包,但是其对 ArcPy支持不是很好。
详见http://forums.arcgis.com/threads/21405-Arcpy-in-SharpDevelop-4.0
3 Python与ArcGIS Engine集成的几种方式对比
前面介绍了Python与ArcGIS Engine集成的三种方法,现在对这三种方法进行一个比较,见下表。
|
开发难宜 |
资源 |
应用范围 |
推荐 |
|
|
利用Python调用AO,编写脚本 |
☆ |
☆☆☆ |
☆☆☆ |
☆☆☆☆ |
|
利用Python调用AO,创建GUI程序 |
☆☆☆ |
☆ |
☆ |
☆ |
|
在AE程序中调用Python |
☆ |
☆☆ |
☆☆☆ |
☆☆☆ |
python脚本特别适合一些批处理操作,如果用户要处理空间数据,而又没有ArcGIS Desktop,只有ArcGIS Engine,利用python调用AO写个小脚本,会非常方便,效率也会很不错。当然如果装了Desktop,可以导入ArcPy站点包,那就会更方便了。
利用Python调用AO,创建GUI程序,也是一种可以的方法,但是个人很不推荐,因为comtypes把AO类型库转换后,AO对象的事件很不好操作,当然如果你很爱折腾,又很闲的话,也可以试试这种方法。
而在AE程序中调用Python的话,在某些情况的话也是很不错的选择,比如已经有一个写好的python文件,而里面有个功能正是我们想要的,我们当然要发挥“拿来主义”了。但是我们可以这样想一下,无论是采用.NET还是JAVA或是C++都能很方便的调用AO,那我们为什么还要舍近求远,在Python中使用AO,然后再调用Python呢?
所以个人觉得在ArcGIS中利用python的最好方式就是编写python脚本,这样便能充分python的优势:简洁、高效。
【转载】Python与ArcGIS Engine的集成的更多相关文章
- [转载]ArcGIS Engine 中的多线程使用
ArcGIS Engine 中的多线程使用 原文链接 http://anshien.blog.163.com/blog/static/169966308201082441114173/ 一直都想写 ...
- ArcGIS Engine 中的多线程使用[转载]
一直都想写写AE中多线程的使用,但一直苦于没有时间,终于在中秋假期闲了下来.呵呵,闲话不说了,进入正题! 大家都了解到ArcGIS中处理大数据量时速度是相当的慢,这时如果你的程序是单线 ...
- ArcGIS Engine断开其他ArcSDE用户连接的解决方案
来自:http://blog.csdn.net/linghe301/article/details/38925481 最近有很多用户咨询在ArcGIS Engine中希望能够实现断开其他客户端连接Ar ...
- 安装ArcGIS Engine 9.3
本文仅用于学习交流,商业用途请支持正版!转载请注明:http://www.cnblogs.com/mxbs/p/6217003.html 准备: ArcGIS Engine 9.3.crack_for ...
- ArcGIS Engine环境下创建自定义的ArcToolbox Geoprocessing工具
在上一篇日志中介绍了自己通过几何的方法合并断开的线要素的ArcGIS插件式的应用程序.但是后来考虑到插件式的程序的配置和使用比较繁琐,也没有比较好的错误处理机制,于是我就把之前的程序封装成一个类似于A ...
- arcgis engine 开发教程系列
版权声明: <ArcGIS Engine+C#实例开发教程>为3SDN(http://www.3sdn.net)原创教程,版权所有.禁止商业用途转载(如需请联系作者),非商业 ...
- 《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现2
原文:<ArcGIS Engine+C#实例开发教程>第七讲 图层符号选择器的实现2 摘要:在第七讲 图层符号选择器的实现的第一阶段中,我们完成了符号选择器窗体的创建与调用.在第二阶段中, ...
- 《ArcGIS Engine+C#实例开发教程》
原文:<ArcGIS Engine+C#实例开发教程> 摘要:<ArcGIS Engine+C#实例开发教程>,面向 ArcGIS Engine(以下简称AE)开发初学者,本教 ...
- 《ArcGIS Engine+C#实例开发教程》第一讲桌面GIS应用程序框架的建立
原文:<ArcGIS Engine+C#实例开发教程>第一讲桌面GIS应用程序框架的建立 摘要:本讲主要是使用MapControl.PageLayoutControl.ToolbarCon ...
随机推荐
- MongoDB学习笔记~管道中的分组实现group+distinct
回到目录 mongoDB的管道是个好东西,它可以将很多操作批处理实现,即将多个命令放入一个管道,然后去顺序的执行它们,今天我要说的是,利用管道中的分组来实现实现中的ditinct+group的效果,即 ...
- 搭建自己的PHP框架心得(三)
h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...
- oracle数据库rman备份计划及恢复
1.rman完全恢复的前提条件:历史的datafile,controlfile和spfile备份,加上完整的archivelog和完好的redolog. 2.rman备份脚本: a.RMAN 0级备份 ...
- Resize Instance 操作详解 - 每天5分钟玩转 OpenStack(41)
Resize 的作用是调整 instance 的 vCPU.内存和磁盘资源. Instance 需要多少资源是定义在 flavor 中的,resize 操作是通过为 instance 选择新的 fla ...
- [Django]下拉表单与模型查询
前言:本文主要针对自定义下拉表单制作,下拉表单的内容是取至于数据库,即动态实现下拉表单 正文: 动态实现下拉表单有两种方法: 一.自己手动写 html 模板中的 <form ...> &l ...
- Unix哲学
01. 模块原则:使用简洁的接口拼合简单的部件. 02. 清晰原则:清晰胜于机巧. 03. 组合原则:设计时考虑拼接组合. 04. 分离原则:策略同机制分离,接口同引擎分离. 05. 简洁原则:设计要 ...
- [No000082]Convert和Parse的区别/Convert.ToInt32()与int.Parse()的区别
(1)这两个方法的最大不同是它们对null值的处理方法: Convert.ToInt32(null)会返回0而不会产生任何异常,但int.Parse(null)则会产生异常. 没搞清楚Convert. ...
- Python3实现TCP端口扫描
在渗透测试的初步阶段通常我们都需要对攻击目标进行信息搜集,而端口扫描就是信息搜集中至关重要的一个步骤.通过端口扫描我们可以了解到目标主机都开放了哪些服务,甚至能根据服务猜测可能存在某些漏洞. TCP端 ...
- NPOI导出Excel合并表头写入公式
protected void Btn1_Click(object sender, EventArgs e) { //建立空白工作簿 IWorkbook workbook = new HSSFWorkb ...
- 让 http 2来得更猛烈些吧
今早在公交车上,把http2的官方讲解文档(还在草案之中)看了一圈,发现相对http 1.1确实改进了不少,完整的文档可通过:://www.gitbook.com/book/ye11ow/http2- ...