¿Accediendo a ArcObjects desde Python?

128

Me gustaría poder escribir algunas cosas que no están expuestas a través de arcgisscripting o ArcPy.

¿Cómo accedo a ArcObjects desde Python?

    
pregunta matt wilkie 22.07.2010 - 23:20

5 respuestas

111

Descargue e instale comtypes *, coloque el módulo Snippets de Mark Cederholm en PYTHONPATH, y listo. conjunto.

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

Para más información, consulte presentaciones de Mark Cederholm para UberPyGeeks en "Uso de ArcObjects en Python" . Hay otros por separado para las perspectivas de los desarrolladores de VBA y C ++. Utilizan Visual Studio (sí, Express está bien) y la Windows SDK , pero no son necesarios, solo ArcGIS, Python y comtypes son suficientes.

Obteniendo el módulo de fragmentos

* Nota para 10.1+ necesita hacer un pequeño cambio a automation.py en el módulo de comtypes. Consulte comtypes de ArcObjects + en 10.1 .

Pasos siguientes

... o: cerebro ido snaky ? Mirar los ejemplos del código c # hace que tus ojos naden, e intenta como si no pudieras pensar como Una grúa ? Mira aquí:

respondido por el matt wilkie 13.04.2017 - 14:34
30

Sí, la presentación de Mark Cederholm que Matt Wilkie menciona anteriormente es un excelente lugar para comenzar. La receta / código que Matt presenta es ciertamente una mancha y probablemente la mejor manera de hacer las cosas. Sin embargo, quería mencionar el método de fuerza bruta que estoy usando en ArcGIS 10.0. Tengo varios scripts de automatización (independientes, fuera del límite de la aplicación) que ejecuto de esta manera, y funcionan bien. Sin embargo, si la velocidad máxima es una preocupación, puede ir con la solución de Matt y terminar con ella.

Utilizo el paquete comtypes para forzar el ajuste de todas las bibliotecas de ArcObjects (.olb). Entonces Python tiene acceso a todos los ArcObjects. Conseguí el código de Frank Perks a través de una publicación del foro ESRI . Tenía mi propio código que esencialmente hacía lo mismo, pero estaba inflado y simplemente funcional, mientras que el suyo es mucho más bonito. Entonces:

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)

Entonces, bastante directamente de la presentación de 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

Eso es todo. Debería tener acceso completo a ArcObjects a partir del objeto pApp que es IApplication en el objeto AppRef. En mi experiencia, la envoltura de las bibliotecas de ArcObjects en la primera ejecución no es obviablemente lenta, y para las ejecuciones posteriores la envoltura no ocurre. Las bibliotecas ya están envueltas y compiladas, por lo que las cosas son mucho más rápidas.

Añadido: Hay una gran precaución que viene con esto. La función NewObj dada aquí asume que el script de Python se está ejecutando en el proceso. De lo contrario, esta función creará objetos en el proceso de Python (es decir, fuera del proceso) y las referencias de los objetos serán incorrectas. Para crear objetos en proceso a partir de una secuencia de comandos de Python externa, debe utilizar IObjectFactory. Vea los comentarios y sugerencias de Kirk Kuykendall en esta publicación de intercambio de pila para más información.

    
respondido por el celticflute 10.01.2011 - 04:48
19
  

¿Cómo accedo a los objetos de arco desde Python?

Si lo que buscas es una funcionalidad específica que existe y está en el código de C ++ Arcobjects, entonces lo mejor sería crear métodos de C ++ para llamarlos ... y luego crear una envoltura de python para acceder a esos métodos de C ++. .

Hay varias formas de acceder a los métodos C ++ desde python, y muchas personas que lo hacen utilizan una herramienta como SWIG para auto -generar las clases de python a partir de las firmas del método C ++. Según mi experiencia, estas API generadas automáticamente se vuelven bastante desagradables al pasar tipos de C ++ no nativos (int, floats) y nunca son muy ' pythonic '.

Mi solución recomendada sería utilizar la API ctypes. Aquí hay un excelente tutorial: enlace

Los pasos básicos son:

  1. escriba algo de su lógica central en C ++, donde cree que el rendimiento de Python podría ser un problema
  2. Compile esa lógica central (en este caso, utilizando las llamadas del método de la API de ArcObject C ++) desde archivos de objetos a una biblioteca compartida (.so) o dinámica (.dll) usando cualquier compilador del sistema (nmake, make, etc.)
  3. Escriba un mapeo de ctypes entre la clase python y la firma del método C ++ [SWIG intenta automatizar esto, pero es fácil, incluso si se usan tipos de objetos locos]
  4. Importe la biblioteca compilada a su programa python y use los enlaces de clase / método enlazados como cualquier otra clase de python.

Esta es probablemente una forma más general de hacer referencia al código C / C ++ desde Python, probablemente será mucho más simple a largo plazo si no tiene que lidiar con objetos COM. También permitirá que todas las funcionalidades específicas del sistema residan en la compilación del objeto de biblioteca vinculado (por lo tanto, el python no será específico de la implementación del sistema / python).

    
respondido por el tmarthal 02.02.2011 - 00:45
18

Otra opción es usar Python para .NET : es muy fácil de configurar y puede funcionar con cualquier DLL de .NET incluyendo ArcObjects.

No he experimentado ningún problema con los objetos en proceso, y abrir una instancia de ArcMap y agregar y manipular capas funcionó bien para mí.

Los únicos requisitos son una carpeta que contenga la biblioteca de Python para .NET y una instalación estándar de Python.

Más detalles y secuencias de comandos de muestra aquí . El script de ejemplo también se puede ver directamente en enlace

Lamentablemente, aunque esto funciona sin problemas en una máquina de desarrollo local, implementarla en otro lugar requiere que se instale ArcObjects SDK y Visual Studio (incluida la edición Express gratuita). Consulte Implementación de archivos DLL de ArcObject .NET

    
respondido por el geographika 17.04.2011 - 14:10
5

Un enfoque que no veo mencionado en las otras respuestas es usar los mismos métodos que usan las bibliotecas arcpy. P.ej. en C: \ Archivos de programa \ ArcGIS \ Desktop10.0 \ arcpy \ arcpy \ cartography.py, vemos que Python llama a las herramientas de ArcObjects usando algunas funciones de conversión de objetos y arreglos.

No sé cuánto se puede publicar al respecto aquí, ya que el código dice "SECRETOS DE COMERCIO: PROPIETARIO ESRI Y CONFIDENCIAL"; Pero también lo encontrarás en otros sitios en la web. De todos modos, esto parece una forma relativamente fácil de llamar a funciones como SimplifyBuilding_cartography() sin instalar comtypes o cualquier otra biblioteca extra.

Editar:

Ver los comentarios de Jason a continuación. Parece que hacer lo anterior no te comprará mucho.

    
respondido por el LarsH 25.01.2013 - 17:28

Lea otras preguntas en las etiquetas