我希望能够编写一些未通过arcgisscripting
或ArcPy 公开的内容。
如何从Python 访问ArcObjects?
我希望能够编写一些未通过arcgisscripting
或ArcPy 公开的内容。
如何从Python 访问ArcObjects?
Answers:
下载并安装comtypes *,将Snippets
Mark Cederholm 的模块放在PYTHONPATH中,一切就绪。
from snippets102 import GetLibPath, InitStandalone
from comtypes.client import GetModule, CreateObject
m = GetModule(GetLibPath() + "esriGeometry.olb")
InitStandalone()
p = CreateObject(m.Point, interface=m.IPoint)
p.PutCoords(2,3)
print p.X, p.Y
有关背景信息,请参阅Mark Cederholm 在UberPyGeeks上的“在Python中使用ArcObjects”的演示。对于VBA和C ++开发人员而言,有单独的观点。他们使用Visual Studio(可以使用Express还是可以的)和Windows SDK,但这不是必需的,仅ArcGIS,Python和comtypes就足够了。
* 请注意,对于10.1+,您需要automation.py
在comtypes模块中进行一些小的更改。请参见10.1中的ArcObjects + comtypes。
是的,Matt Wilkie上面提到的Mark Cederholm的演讲是一个很好的起点。Matt提出的配方/代码无疑是一种巧妙的方法,并且可能是解决问题的最佳方法。不过,我想提一下我在ArcGIS 10.0中使用的蛮力方法。我有几种以这种方式运行的自动化脚本(独立的,在应用程序边界之外),它们运行良好。但是,如果需要考虑最大速度,则可以采用Matt的解决方案并完成它。
我使用comtypes包强制包装所有ArcObjects库(.olb)。然后,Python可以访问所有ArcObjects。我通过一个ESRI论坛帖子从Frank Perks获得了包装代码。我有自己的代码,基本上执行了相同的操作,但是它肿且仅具有功能,而他的代码更漂亮。所以:
import sys, os
if '[path to your Python script/module directory]' not in sys.path:
sys.path.append('[path to your Python script/module directory]')
import comtypes
#force wrapping of all ArcObjects libraries (OLBs)
import comtypes.client
# change com_dir to whatever it is for you
com_dir = r'C:\Program Files (x86)\ArcGIS\Desktop10.0\com'
coms = [os.path.join(com_dir, x) for x in os.listdir(com_dir) if os.path.splitext(x)[1].upper() == '.OLB']
map(comtypes.client.GetModule, coms)
然后,完全是马克·塞德霍尔姆的演讲:
import comtypes.gen.esriFramework
pApp = GetApp()
def GetApp():
"""Get a hook into the current session of ArcMap"""
pAppROT = NewObj(esriFramework.AppROT, esriFramework.IAppROT)
iCount = pAppROT.Count
if iCount == 0:
print 'No ArcGIS application currently running. Terminating ...'
return None
for i in range(iCount):
pApp = pAppROT.Item(i) #returns IApplication on AppRef
if pApp.Name == 'ArcMap':
return pApp
print 'No ArcMap session is running at this time.'
return None
def NewObj(MyClass, MyInterface):
"""Creates a new comtypes POINTER object where\n\
MyClass is the class to be instantiated,\n\
MyInterface is the interface to be assigned"""
from comtypes.client import CreateObject
try:
ptr = CreateObject(MyClass, interface=MyInterface)
return ptr
except:
return None
而已。您应该具有对ArcObjects的完全访问权限,从pRef对象(即AppRef对象上的IApplication)开始。以我的经验,第一次运行时对ArcObjects库的包装不会令人讨厌,并且对于后续运行,也不会发生包装。库已经包装和编译,因此速度更快。
补充: 随之而来的是一个很大的警告。这里给出的NewObj函数假定Python脚本正在进程内运行。如果不是,此函数将在Python进程(即进程外)中创建对象,并且对象引用将是错误的。要从外部Python脚本创建过程中对象,应使用IObjectFactory。有关更多信息,请参见此stackexchange 帖子中的 Kirk Kuykendall的评论和提示。
如何从python访问arcobjects?
如果您要寻找的是C ++ Arcobjects代码中存在的特定功能,那么最好的选择是创建C ++方法来调用它们。
有很多方法可以从python访问C ++方法,许多人使用诸如SWIG之类的工具从C ++方法签名自动生成python类。根据我的经验,这些自动生成的API在传递非本机C ++类型(int,float)时会变得非常讨厌,并且它们从来都不是“ pythonic ”的。
我推荐的解决方案是使用ctypes API。一个很棒的教程在这里:http : //python.net/crew/theller/ctypes/tutorial.html
基本步骤是:
这可能是从python内部引用C / C ++代码的更通用的方法,从长远来看,如果不必处理COM对象,它可能会变得更加简单。它还将允许所有特定于系统的功能驻留在链接库对象的编译中(因此python将不是特定于系统/ python实现的)。
另一个选择是将Python用于.NET-设置非常容易,并且可以与包括ArcObjects在内的任何.NET DLL一起使用。
我在处理过程中没有遇到过任何问题,因此打开ArcMap实例并添加和操作图层对我来说效果很好。
唯一的要求是一个包含Python for .NET库的文件夹和一个标准的Python安装。
更多详细信息和示例脚本在此处。示例脚本也可以直接在http://gist.github.com/923954上看到。
不幸的是,尽管这在本地开发计算机上没有问题,但将其部署到其他地方则需要安装ArcObjects SDK和Visual Studio(包括免费的Express版本)。请参阅部署ArcObject .NET DLL
在其他答案中没有提到的一种方法是使用与arcpy库本身使用的方法相同的方法。例如,在C:\ Program Files \ ArcGIS \ Desktop10.0 \ arcpy \ arcpy \ cartography.py中,我们看到Python使用一些fixargs和对象转换函数调用ArcObjects工具。
我不希望在此处发布多少代码,因为代码显示“ TRADE SECRETS:ESRI专有和机密”;但您也可以在网络上的其他地方找到它。无论如何,这看起来是调用函数的相对简单的方法,例如SimplifyBuilding_cartography()
无需安装comtypes或任何其他额外的库。
编辑:
请参阅下面的Jason评论。听起来像做上面的事情不会买很多东西。