在 Python 中使用 ArcObjects

1. 为什么使用 Python?

  • ArcGIS 10.0 之后官方将不再提供对 VBA 的支持。
  • 从 10.0 版本开始,ArcMap 和 ArcCatalog 里面都集成了 Python 命令行。
  • ESRI 提供了 Python 的脚本对象。
  • IDLE 是一个像样的开发和调试环境。
  • Python 中可以使用 ArcObjects。

2. 关于地理处理对象

  • 从 9.3(arcgisscripting) 和 10.0(arcpy)开始, Python 随时都可以使用地理处理对象。
  • 在 9.3 中:包含了诸如游标之类的数据访问对象等附加功能。
  • 在 10.0 中:包含了诸如地图文档自动化等附加功能。
  • 尽管如此,大量的功能只能通过 ArcObjects 才能实现。

3. 使用 ArcObjects

 

        在 Python 中要调用基于 COM 的 ArcObjects 就得使用 comtypes 模块。从以下地址下载:http://sourceforge.net/projects/comtypes/

 

读取和导入模块

def GetLibPath(): ## 返回 ArcGIS 的 COM 路径,比如: "C:/Program Files/ArcGIS/com/" import _winreg keyESRI = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "SOFTWARE//ESRI//ArcGIS") return _winreg.QueryValueEx(keyESRI, "InstallDir")[0] + "com//" def GetModule(sModuleName): import comtypes from comtypes.client import GetModule sLibPath = GetLibPath() GetModule(sLibPath + sModuleName) # 主程序中就可以直接使用 GetModule 来载入需要的库 GetModule("esriGeometry.olb") import comtypes.gen.esriGeometry as esriGeometry # 或者 from comtypes.gen.esriGeometry import Point, IPoint # 不推荐 import *

 

 

创建和对象类型转换

def NewObj(MyClass, MyInterface): from comtypes.client import CreateObject try: ptr = CreateObject(MyClass, interface=MyInterface) return ptr except: return None def CType(obj, interface): try: newobj = obj.QueryInterface(interface) return newobj except: return None def CLSID(MyClass): return str(MyClass._reg_clsid_)

 

 

独立运行程序的许可

pInit = NewObj(esriSystem.AoInitialize, esriSystem.IAoInitialize) # 另外 10.0 之后,初始化许可之前,必须选择版本。详见下文。 eProduct = esriSystem.esriLicenseProductCodeArcEditor licenseStatus = pInit.IsProductCodeAvailable(eProduct) if licenseStatus == esriSystem.esriLicenseAvailable: licenseStatus = pInit.Initialize(eProduct) return (licenseStatus == esriSystem.esriLicenseCheckedOut) # 或者使用地理处理对象来代替 import arcgisscripting gp = arcgisscripting.create(9.3) gp.setproduct("ArcEditor")

 

 

从外部寻找一个已运行的 ArcGIS 实例

if not (app == "ArcMap" or app == "ArcCatalog"): return None pAppROT = NewObj(esriFramework.AppROT, esriFramework.IAppROT) iCount = pAppROT.Count if iCount == 0: return None for i in range(iCount): pApp = pAppROT.Item(i) if app == "ArcCatalog": if CType(pApp, esriCatalogUI.IGxApplication): return pApp continue if CType(pApp, esriArcMapUI.IMxApplication): return pApp return None

 

 

获取已选择的图元

pApp = GetApp() # ...其他一些操作 pDoc = pApp.Document pMxDoc = CType(pDoc, esriArcMapUI.IMxDocument) pMap = pMxDoc.FocusMap pFeatSel = pMap.FeatureSelection pEnumFeat = CType(pFeatSel, esriGeoDatabase.IEnumFeature) pEnumFeat.Reset() pFeat = pEnumFeat.Next() if not pFeat: print "No selection found." return pShape = pFeat.ShapeCopy eType = pShape.GeometryType if eType == esriGeometry.esriGeometryPoint: print "Geometry type = Point" # ...其他一些操作

 

 

 

使用 IObjectFactory 创建会话对象。 获取了 ArcGIS 程序的实例之后,就可以使用 IObjectFactory 创建新的对象

pApp = GetApp() pFact = CType(pApp, esriFramework.IObjectFactory) pUnk = pFact.Create(CLSID(esriCarto.TextElement)) pTextElement = CType(pUnk, esriCarto.ITextElement)

在 10.0 中,可以使用 ArcGIS 程序里面内置的 Python 命令行运行脚本。另外,也可以使用 AppRef 获得进程的句柄
pApp = NewObj(esriFramework.AppRef, esriFramework.IApplication)

 

 

 

UID 和枚举

pApp = GetApp() # ...其他一些操作 pID = NewObj(esriSystem.UID, esriSystem.IUID) pID.Value = CLSID(esriEditor.Editor) pExt = pApp.FindExtensionByCLSID(pID) pEditor = CType(pExt, esriEditor.IEditor) if pEditor.EditState == esriEditor.esriStateEditing: pWS = pEditor.EditWorkspace pDS = CType(pWS, esriGeoDatabase.IDataset) print "Workspace name: " + pDS.BrowseName print "Workspace category: " + pDS.Category

同样,也可以返回多个值

iEdgeEID, bReverse, oWeight = pForwardStar.QueryAdjacentEdge(i)

 

 

 

空值、IsNull 和 None。 支持使用 None 作为参数中的空值

iOpt = esriCarto.esriViewGraphics + esriCarto.esriViewGraphicSelection pActiveView.PartialRefresh(iOpt, None, None)

通过布尔测试来判断是否空值,使用 is None 来判断是否数据库中的空值(图元属性的空值)

pCursor = pTab.Search(pQF, True) pRow = pCursor.NextRow() if not pRow: print "Query returned no rows" return Val = pRow.Value(pTab.FindField(sFieldName)) if Val is None: print "Null value"

 

 

 

写入和检索属性 (最好是使用地理处理工具来创建表以及增加字段)

pNewField = NewObj(esriGeoDatabase.Field, esriGeoDatabase.IField) pFieldEdit = CType(pNewField, esriGeoDatabase.IFieldEdit) pFieldEdit._Name = "LUMBERJACK" pFieldEdit._Type = esriGeoDatabase.esriFieldTypeString pFieldEdit._Length = 50 pFieldsEdit._Field[1] = pNewField pOutTable = pFWS.CreateTable(sTableName, pOutFields, None, None, "") iField = pOutTable.FindField("LUMBERJACK") print "'LUMBERJACK' field index = ", iField pRow = pOutTable.CreateRow() pRow.Value[iField] = "I sleep all night and I work all day" pRow.Store()

 

 


创建一个用于 ArcMap 或 ArcCatalog 的 COM 对象

  1. 新建一个 IDL 文件,用来定义对象和接口。
  2. 使用 MIDL 编译器编译并生成一个 TLB 文件:midl DemoTool.idl
  3. 使用 Python 实现这个类并注册
  4. 注册 COM 对象: python DemoTool.py -regserver

 

其他一些建议

  • 对 COM 的调用有任何疑问都可以查看 comtypes 生成的封装代码(在 Python25/Lib/sitepackages/comtypes/gen 目录下)
  • 避免在 Python 中大量的使用细粒度的 ArcObjects
  • 为了获得更好的性能,建议使用 C++ 去创建粗粒度的 COM 对象
  • 使用地理处理对象(geoprocessing)和地理处理工具(arctoolsbox)来简化任务(提高性能)
  • 注意阅读桌面版帮助,了解脚本中可以使用哪些功能

 

本文翻译自 Mark Cederholm 的 PDF:Using ArcObjects in Python

示例代码:http://www.pierssen.com/arcgis10/python.htm

 

 

 

你可能感兴趣的:(python,脚本,import,VBA,interface,编译器)