Vorrei essere in grado di scrivere alcune cose che non sono state scoperte tramite arcgisscripting
ArcPy.
Come posso accedere ad ArcObjects da Python?
Vorrei essere in grado di scrivere alcune cose che non sono state scoperte tramite arcgisscripting
ArcPy.
Come posso accedere ad ArcObjects da Python?
Risposte:
Scarica e installa i comtypes *, metti il Snippets
modulo da Mark Cederholm in PYTHONPATH e sei pronto.
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
Per lo sfondo vedi le presentazioni di Mark Cederholm per UberPyGeeks su "Usare ArcObjects in Python" . Ci sono quelli separati per le prospettive degli sviluppatori VBA e C ++. Usano Visual Studio (sì Express è ok) e Windows SDK , ma questi non sono necessari, solo ArcGIS, Python e i tipi sono sufficienti.
* Nota per 10.1+ è necessario apportare una piccola modifica al automation.py
modulo Comtypes. Vedi ArcObjects + comtypes alla 10.1 .
... o: cervello impazzito ? Guardare gli esempi di codice c # ti fa nuotare gli occhi e provare come potresti non riuscire a pensare come una gru ? Guarda qui:
Sì, la presentazione di Mark Cederholm che Matt Wilkie menziona sopra è un ottimo punto di partenza. La ricetta / codice che Matt presenta è sicuramente una chiazza e probabilmente il modo migliore per affrontare le cose. Volevo menzionare, tuttavia, il metodo della forza piuttosto bruta che sto usando in ArcGIS 10.0. Ho diversi script di automazione (standalone, al di fuori del limite dell'applicazione) che eseguo in questo modo e funzionano perfettamente. Se la velocità massima è un problema, potresti semplicemente scegliere la soluzione di Matt e farla finita.
Uso il pacchetto comtypes per forzare il wrapping di tutte le librerie ArcObjects (.olb). Quindi Python ha accesso a tutti gli ArcObjects. Ho ricevuto il codice di wrapping da Frank Perks tramite un post sul forum ESRI . Avevo il mio codice che essenzialmente faceva la stessa cosa, ma era gonfio e semplicemente funzionale, mentre il suo è molto più carino. Così:
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)
Quindi, praticamente uscito dalla presentazione di Mark Cederholm:
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
Questo è tutto. Dovresti avere pieno accesso ad ArcObjects a partire dall'oggetto pApp che è IApplication sull'oggetto AppRef. Nella mia esperienza, il wrapping delle librerie ArcObjects alla prima esecuzione non è discutibilmente lento e, per le successive, il wrapping non avviene. Le librerie sono già raggruppate e compilate, quindi le cose sono molto più veloci.
Aggiunto: c'è una grande cautela che ne deriva. La funzione NewObj qui fornita presuppone che lo script Python sia in esecuzione nel processo. In caso contrario, questa funzione creerà oggetti nel processo Python (es. Fuori processo) e i riferimenti agli oggetti saranno errati. Per creare oggetti di processo da uno script Python esterno è necessario utilizzare IObjectFactory. Vedi i commenti e i suggerimenti di Kirk Kuykendall in questo post di stackexchange per maggiori informazioni.
Come posso accedere ad arcobjects da Python?
Se quello che stai cercando è una funzionalità specifica che esiste ed è nel codice Arcobjects C ++, allora la soluzione migliore sarebbe quella di creare metodi C ++ per chiamarli .... e quindi creare un wrapper Python per accedere a quei metodi C ++.
Esistono diversi modi per accedere ai metodi C ++ da Python e molte persone che lo fanno usano uno strumento come SWIG per generare automaticamente le classi Python dalle firme del metodo C ++. È stata la mia esperienza che queste API autogenerate diventano piuttosto brutte quando passano tipi C ++ non nativi (int, float) e non sono mai molto " pitoniche ".
La mia soluzione raccomandata sarebbe quella di utilizzare l'API ctypes. Un grande tutorial è qui: http://python.net/crew/theller/ctypes/tutorial.html
I passaggi di base sono:
Questo è probabilmente il modo più generale per fare riferimento al codice C / C ++ dall'interno di Python, probabilmente sarà molto più semplice a lungo termine se non si ha a che fare con oggetti COM. Consentirà inoltre a tutte le funzionalità specifiche del sistema di risiedere nella compilazione dell'oggetto libreria collegato (quindi il python non sarà specifico dell'implementazione di sistema / python).
Un'altra opzione è utilizzare Python per .NET : è molto facile da configurare e può funzionare con qualsiasi DLL .NET incluso ArcObjects.
Non ho riscontrato alcun problema con gli oggetti in-process e l'apertura di un'istanza di ArcMap e l'aggiunta e la manipolazione dei livelli ha funzionato bene per me.
Gli unici requisiti sono una cartella contenente la libreria Python per .NET e un'installazione standard di Python.
Maggiori dettagli e script di esempio qui . Lo script di esempio può anche essere visualizzato direttamente all'indirizzo http://gist.github.com/923954
Sfortunatamente, mentre questo funziona senza problemi su una macchina di sviluppo locale, la sua distribuzione altrove richiede ArcObjects SDK e Visual Studio (compresa l'edizione Express gratuita) da installare. Vedere Distribuzione di DLL ArcObject .NET
Un approccio che non vedo menzionato nelle altre risposte è quello di utilizzare gli stessi metodi utilizzati dalle stesse librerie arcpy. Ad esempio in C: \ Programmi \ ArcGIS \ Desktop10.0 \ arcpy \ arcpy \ cartography.py, vediamo Python che chiama gli strumenti ArcObjects usando alcune funzioni di correzione e conversione degli oggetti.
Non so quanto sia giusto pubblicarlo qui, poiché il codice dice "SEGRETI COMMERCIALI: ESRI PROPRIETARI E RISERVATI"; ma lo troverai anche altrove sul web. Comunque, questo sembra un modo relativamente semplice per chiamare funzioni come SimplifyBuilding_cartography()
senza installare comtype o altre librerie extra.
Modificare:
Vedi i commenti di Jason qui sotto. Sembra che fare quanto sopra non ti comprerà molto.