Ich möchte in der Lage sein, einige Dinge zu arcgisscripting
skripten , die nicht über oder ArcPy verfügbar gemacht werden.
Wie greife ich von Python aus auf ArcObjects zu ?
Ich möchte in der Lage sein, einige Dinge zu arcgisscripting
skripten , die nicht über oder ArcPy verfügbar gemacht werden.
Wie greife ich von Python aus auf ArcObjects zu ?
Antworten:
Laden Sie comtypes * herunter und installieren Sie es , setzen Sie das Snippets
Modul von Mark Cederholm in PYTHONPATH ein und schon sind Sie fertig.
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
Hintergrundinformationen finden Sie in den Präsentationen von Mark Cederholm für UberPyGeeks zum Thema "Verwenden von ArcObjects in Python" . Für VBA- und C ++ - Entwicklerperspektiven gibt es separate. Sie verwenden Visual Studio (ja, Express ist in Ordnung) und das Windows SDK , aber diese sind nicht erforderlich, nur ArcGIS, Python und Comtypes sind ausreichend.
* Hinweis für 10.1+ müssen Sie automation.py
im comtypes-Modul eine kleine Änderung vornehmen. Siehe ArcObjects + comtypes unter 10.1 .
... oder: Gehirn schlapp gemacht ? Wenn Sie sich die C # -Codebeispiele ansehen, schwimmen Ihre Augen und versuchen Sie, wie Sie vielleicht einfach nicht wie ein Kran denken können ? Schau hier:
Ja, Mark Cederholms Präsentation, die Matt Wilkie oben erwähnt, ist ein großartiger Anfang. Das Rezept / der Code, den Matt vorlegt, ist mit Sicherheit ein geschickter und wahrscheinlich der beste Weg, um Dinge zu erledigen. Ich wollte jedoch die ziemlich brachiale Methode erwähnen, die ich in ArcGIS 10.0 verwende. Ich habe mehrere Automatisierungsskripte (eigenständig, außerhalb der Anwendungsgrenzen), die ich auf diese Weise ausführe, und sie funktionieren einwandfrei. Wenn es jedoch um die maximale Geschwindigkeit geht, können Sie sich einfach für Matts Lösung entscheiden und damit fertig werden.
Ich verwende das comtypes-Paket, um das Umbrechen aller ArcObjects-Bibliotheken (.olb) zu erzwingen. Dann hat Python Zugriff auf alle ArcObjects. Ich habe den Code von Frank Perks über ein ESRI-Forum erhalten . Ich hatte meinen eigenen Code, der im Wesentlichen dasselbe tat, aber er war aufgebläht und nur funktional, während sein Code viel hübscher ist. Damit:
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)
Dann, so ziemlich direkt aus Mark Cederholms Präsentation:
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
Das ist es. Sie sollten vollen Zugriff auf ArcObjects haben, beginnend mit dem pApp-Objekt, das IApplication für das AppRef-Objekt ist. Nach meiner Erfahrung ist das Umschließen der ArcObjects-Bibliotheken beim ersten Durchlauf nicht unangenehm langsam, und bei nachfolgenden Durchläufen erfolgt das Umschließen nicht. Die Bibliotheken sind bereits verpackt und kompiliert, so dass die Dinge viel schneller laufen.
Hinzugefügt: Es gibt eine große Vorsicht, die damit einhergeht. Die hier angegebene NewObj-Funktion setzt voraus, dass das Python-Skript in-process ausgeführt wird. Wenn nicht, erstellt diese Funktion Objekte im Python-Prozess (dh außerhalb des Prozesses), und die Objektreferenzen sind falsch. Um in einem Prozess Objekte aus einem externen Python-Skript zu erstellen, sollten Sie IObjectFactory verwenden. Weitere Informationen finden Sie in den Kommentaren und Tipps von Kirk Kuykendall in diesem Stapelwechsel-Beitrag .
Wie greife ich mit Python auf ArcObjects zu?
Wenn Sie nach einer bestimmten Funktionalität suchen, die vorhanden ist und im C ++ - Arcobjects-Code enthalten ist, sollten Sie am besten C ++ - Methoden erstellen, um sie aufzurufen. Erstellen Sie anschließend einen Python-Wrapper, um auf diese C ++ - Methoden zuzugreifen.
Es gibt eine ganze Reihe von Möglichkeiten, über Python auf C ++ - Methoden zuzugreifen, und viele Leute verwenden dazu ein Tool wie SWIG , um die Python-Klassen automatisch aus den C ++ - Methodensignaturen zu generieren. Ich habe die Erfahrung gemacht, dass diese automatisch generierten APIs beim Übergeben nicht nativer C ++ - Typen (int, floats) ziemlich unangenehm werden und nie sehr " pythonisch " sind.
Meine empfohlene Lösung wäre die Verwendung der ctypes-API. Ein großartiges Tutorial finden Sie hier: http://python.net/crew/theller/ctypes/tutorial.html
Die grundlegenden Schritte sind:
Dies ist wahrscheinlich eine allgemeinere Methode, um C / C ++ - Code aus Python heraus zu referenzieren. Auf lange Sicht wird dies wahrscheinlich viel einfacher, wenn Sie sich nicht mit COM-Objekten befassen müssen. Es ermöglicht auch, dass alle systemspezifischen Funktionen in der Kompilierung des verknüpften Bibliotheksobjekts enthalten sind (sodass der Python nicht system- / python-spezifisch ist).
Eine andere Option ist die Verwendung von Python für .NET. Dies ist sehr einfach einzurichten und kann mit allen .NET-DLLs einschließlich ArcObjects verwendet werden.
Ich habe keine Probleme mit In-Process-Objekten festgestellt. Das Öffnen einer Instanz von ArcMap und das Hinzufügen und Bearbeiten von Layern hat für mich problemlos funktioniert.
Die einzigen Voraussetzungen sind ein Ordner mit der Python for .NET-Bibliothek und eine Standard-Python-Installation.
Weitere Details und Beispielskript hier . Das Beispielskript kann auch direkt unter http://gist.github.com/923954 eingesehen werden
Obwohl dies auf einem lokalen Entwicklungscomputer problemlos funktioniert, müssen für die Bereitstellung an einem anderen Ort das ArcObjects SDK und Visual Studio (einschließlich der kostenlosen Express-Edition) installiert sein. Siehe Bereitstellen von ArcObject .NET-DLLs
Ein Ansatz, der in den anderen Antworten nicht erwähnt wird, besteht darin, die gleichen Methoden zu verwenden, die die Arcpy-Bibliotheken selbst verwenden. In C: \ Programme \ ArcGIS \ Desktop10.0 \ arcpy \ arcpy \ cartography.py wird beispielsweise Python beim Aufrufen von ArcObjects-Tools mit einigen Fixargs und Objektkonvertierungsfunktionen angezeigt.
Ich weiß nicht, wie viel es in Ordnung ist, hier darüber zu posten, da der Code "TRADE SECRETS: ESRI PROPRIETARY AND CONFIDENTIAL" lautet. Sie finden es aber auch an anderer Stelle im Internet. SimplifyBuilding_cartography()
Auf jeden Fall scheint dies eine relativ einfache Möglichkeit zu sein, Funktionen aufzurufen, ohne comtypes oder andere zusätzliche Bibliotheken zu installieren.
Bearbeiten:
Siehe Jasons Kommentare unten. Klingt so, als würde Ihnen das oben Genannte nicht viel bringen.