Python에서 ArcObject에 액세스 하시겠습니까?


132

arcgisscripting나 ArcPy 를 통해 노출되지 않은 것들을 스크립팅하고 싶습니다.

Python에서 ArcObject에 어떻게 액세스 합니까?


3
프로덕션 환경에서 이러한 방법을 사용하려고 생각하는 사람이 있습니까? 몇 년 전 UC에서 필자는 대부분의 Python 모듈을 작성하는 ESRI C ++ 개발자 중 한 명과 이야기했으며 프로덕션 환경에서 IronPython을 사용하는 것에 대해 강력하게 반대했지만 몇 년 전이었습니다.
채드 쿠퍼

답변:


113

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

배경은 "Python에서 ArcObjects 사용"에 대한 UberPyGeeks에 대한 Mark Cederholm의 프리젠 테이션 을 참조하십시오 . VBA 및 C ++ 개발자 관점에 대한 별도의 사항이 있습니다. 그들은 사용하는 비주얼 스튜디오 (예 Express는 괜찮습니다)와 윈도우 SDK를 단지는 ArcGIS, 파이썬과 comtypes이 충분하다, 그러나 이들은 필요하지 않습니다.

스 니펫 모듈 얻기

* 10.1+의automation.py 경우 comtypes 모듈에서 약간 변경해야 합니다. 10.1의 ArcObjects + comtypes를 참조하십시오 .


다음 단계

... 또는 : 뇌가 gone 거리다 ? C # 코드 예제를 살펴보면 눈이 헤엄 치고 크레인 처럼 생각할 수없는 것처럼 시험해보십시오 . 이봐:


10
이 스레드는 주목을 받았으며, 약간의 오해가 떠있는 것 같습니다. Python에서 ArcObject를 사용하기 위해 Visual Studio 또는 MIDL 컴파일러가 필요하지 않습니다. comtypes 패키지 만 있으면됩니다. 프레젠테이션에는 Python을 사용하여 COM 구성 요소를 만드는 고급 실습이 포함되었지만 UberPyGeeks를위한 것입니다. snippets.py 파일에는 필요한 모든 예제가 포함되어 있습니다.

1
@ Mark, 수정 해 주셔서 감사합니다. 분명히하기 위해 : 위의 레시피에서 ctypes 가 이미 설치되어 있는 한 1, 3, 4 단계를 제거 할 수 있습니까?
matt wilkie

2
네. 실험실에서 테스트했습니다. comtypes 만 설치하면됩니다.
RK

@RK, 좋아요! 확인해 주셔서 감사합니다. 답변을 최신 상태로 유지하십시오.
matt wilkie

1
스 니펫 모듈은 github.com/maphew/arcplus/tree/master/arcplus/ao 에서 설치 가능한 ao 모듈 로 다시 캐스트됩니다 (10.3으로 업데이트되었습니다. 10.2의 이전 버전 파일 참조). 몇 가지 버그가 해결되면 주요 답변을 업데이트합니다.
매트 윌키

32

예, Matt Wilkie가 언급 한 Mark Cederholm의 프레젠테이션은 시작하기에 좋은 곳입니다. Matt가 제시하는 레시피 / 코드는 분명 매끄럽고 아마도 가장 좋은 방법입니다. 그래도 ArcGIS 10.0에서 사용하는 다소 무차별 한 방법을 언급하고 싶었습니다. 이 방법으로 실행하는 여러 자동화 스크립트 (독립형, 응용 프로그램 경계 외부)가 있으며 제대로 작동합니다. 그러나 최대 속도가 중요하다면 Matt의 솔루션을 사용하여 완료 할 수 있습니다.

comtypes 패키지를 사용하여 모든 ArcObjects 라이브러리 (.olb)를 강제로 줄 바꿈합니다. 그러면 파이썬은 모든 ArcObject에 접근 할 수 있습니다. 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)

그런 다음 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

그게 다야. AppRef 객체에서 IApplication 인 pApp 객체로 시작하여 ArcObject에 완전히 액세스 할 수 있어야합니다. 필자의 경험에 따르면 첫 번째 실행에서 ArcObjects 라이브러리 래핑은 느리게 진행되지 않으며 후속 실행에서는 래핑이 발생하지 않습니다. 라이브러리는 이미 랩핑되고 컴파일되어 있으므로 훨씬 더 빠릅니다.

추가 : 이것과 함께 큰주의가 있습니다. 여기에 주어진 NewObj 함수는 파이썬 스크립트가 프로세스 내에서 실행되고 있다고 가정합니다. 그렇지 않으면이 함수는 Python 프로세스에서 오브젝트를 작성하고 (즉, 프로세스 외부에서) 오브젝트 참조가 잘못됩니다. 외부 Python 스크립트에서 프로세스 개체를 만들려면 IObjectFactory를 사용해야합니다. 자세한 내용은 이 스택 교환 게시물 에서 Kirk Kuykendall의 의견과 팁 을 참조하십시오.


1
이 방법의 좋은 점은 Visual Studio를 설치할 필요가 없다는 것입니다. Visual Studio를 설치할 필요가없는 경우는 COM 개체를 등록하는 것만으로도 매우 무겁습니다. 이 순수한 파이썬 방법에 대해 알고 있다면 Cederholm의 경로를 시도하지 않았을 것입니다. ;-)
matt wilkie

1
이 답변에서이 개념을 약간 확장하여 가져 오기를 수행하고 형식 라이브러리를 한 단계 프로세스로 묶습니다
blah238

20

파이썬에서 arcobjects에 어떻게 액세스합니까?

당신이 찾고있는 것이 존재하고 C ++ Arcobjects 코드에있는 특정 기능이라면, 가장 좋은 방법은 C ++ 메소드를 호출하여 호출합니다 .... 그리고 파이썬 래퍼를 만들어 C ++ 메소드에 액세스하는 것이 가장 좋습니다.

파이썬에서 C ++ 메소드에 액세스하는 방법은 꽤 많으며 SWIG 와 같은 도구를 사용 하여 C ++ 메소드 서명에서 파이썬 클래스를 자동 생성하는 많은 사람들이 있습니다 . 네이티브가 아닌 C ++ 유형 (int, float)을 전달할 때 이러한 자동 생성 API가 상당히 불쾌하고 결코 ' pythonic ' 이 아닌 것은 내 경험 이었습니다.

내 권장 솔루션은 ctypes API를 사용하는 것입니다. 훌륭한 자습서는 다음과 같습니다. http://python.net/crew/theller/ctypes/tutorial.html

기본 단계는 다음과 같습니다.

  1. 파이썬 성능이 문제가 될 수 있다고 생각하는 핵심 로직을 C ++로 작성하십시오.
  2. 시스템 컴파일러 (nmake, make 등)를 사용하여 객체 파일에서 공유 (.so) 또는 동적 라이브러리 (.dll)로 코어 로직 (이 경우 ArcObject C ++ API 메소드 호출을 사용하여)을 컴파일하십시오.
  3. python 클래스와 C ++ 메소드 서명 사이에 ctypes 맵핑 작성 [SWIG는이를 자동화하려고 시도하지만, 미친 오브젝트 유형을 사용하더라도 쉽습니다.]
  4. 컴파일 된 라이브러리를 파이썬 프로그램으로 가져오고 다른 파이썬 클래스와 마찬가지로 바인딩 된 클래스 / 메소드 바인딩을 사용하십시오!

이것은 아마도 파이썬 내에서 C / C ++ 코드를 참조하는 더 일반적인 방법 일 것입니다. COM 객체를 처리 할 필요가 없다면 장기적으로 훨씬 더 간단 할 것입니다. 또한 모든 시스템 특정 기능이 연결된 라이브러리 객체의 컴파일에 상주 할 수 있습니다 (따라서 파이썬은 시스템 / 파이썬 구현에 한정되지 않음).


3
이것은 ArcObject와 상호 작용하는 가장 좋은 방법입니다. comtypes의 사용은 프로토 타이핑에는 좋지만 C 확장을 작성하면 C ++ / Python 객체 장벽을 많이 넘지 않기 때문에 좋은 Pythonic 디자인 (생각해야하기 때문에)과 더 나은 성능을 얻을 수 있습니다. 실용적인 목적을 위해 설계 / 개발 / 디버그하기가 더 어려워서 더 빠르고 더티가 창 밖으로 나옵니다.
Jason Scheirer

18

또 다른 옵션은 Python을 .NET 에 사용하는 것 입니다. 이것은 설정이 매우 쉽고 ArcObject를 포함한 모든 .NET DLL과 함께 사용할 수 있습니다.

프로세스 중 개체 문제가 발생하지 않았으며 ArcMap 인스턴스를 열고 레이어를 추가하고 조작하는 것이 나에게 효과적이었습니다.

유일한 요구 사항은 Python for .NET 라이브러리가 포함 된 폴더와 표준 Python 설치입니다.

자세한 내용 및 샘플 스크립트는 여기를 참조 하십시오 . 샘플 스크립트는 http://gist.github.com/923954 에서 직접 볼 수도 있습니다.

불행히도 로컬 개발 시스템에서는 문제없이 작동하지만 다른 위치에 배포하려면 ArcObjects SDK 및 Visual Studio (무료 Express 버전 포함)를 설치해야합니다. ArcObject .NET DLL 배포를 참조하십시오.


레시피는 명확하고 명쾌하며 잘 표현되어 있습니다. Geographika에게 감사합니다! 귀하의 답변에 최소한의 스크립트 스 니펫을 포함시켜 사이트가 리노베이션되는 경우 자체 답변을 얻을 수 있도록 권장합니다.
matt wilkie

1
그것은이 오래된 블로그 게시물 ( gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html ) 에서 정확히 한 일 이며 예상대로 작동하지만 Python 스크립트가 이해하는 결과 (문자열, 숫자)를 반환해야합니다 또는 무효).
사무엘


5

다른 답변에서 언급하지 않은 한 가지 방법은 arcpy 라이브러리 자체에서 사용하는 것과 동일한 방법을 사용하는 것입니다. 예를 들어 C : \ Program Files \ ArcGIS \ Desktop10.0 \ arcpy \ arcpy \ cartography.py에서 일부 fixargs 및 객체 변환 함수를 사용하여 Python이 ArcObjects 도구를 호출하는 것을 볼 수 있습니다.

코드에 "무역 비밀 : ESRI 독점 및 기밀"이라고 표시되어 있기 때문에 여기에 게시해도 괜찮습니다. 웹의 다른 곳에서도 찾을 수 있습니다. 어쨌든, 이것은 SimplifyBuilding_cartography()comtype이나 다른 추가 라이브러리를 설치하지 않고 함수를 호출하는 비교적 쉬운 방법처럼 보입니다 .

편집하다:

아래 Jason의 의견을 참조하십시오. 위와 같은 소리는 당신을 많이 사지 않을 것입니다.


나는 너무 많은 부두처럼 보입니다.
blah238

1
완전히 노출 된 arcobject 세트를 호출하지 않습니다.
Jason Scheirer

@JasonScheirer는 가능한 한 직선 Arcpy API보다 ArcObjects (제 생각에는)에 어느 정도 더 많은 액세스를 허용하며 다른 라이브러리를 설치할 필요가 없다는 이점이 있습니다. 후자는 다른 사람들이 사용할 수있는 도구를 개발하는 경우 중요 할 수 있습니다. 이 방법을 통해 액세스 할 수있는 내용의 전체 범위를 알고 싶습니다. 특정 목적에 충분할 수 있습니다. (지금은 확인할 수 없습니다-회사 LAN에 있지 않습니다.)
LarsH

1
사실이 아니라고 확신 할 수 있습니다. 나는 그것을 많이 개발했다.
Jason Scheirer

1
당신은 할 수 없습니다. "ArcObject"는이 경우 약간 잘못되었습니다. 기본 개체에 도달 할 수있는 방법이 없으며 arcgisscripting / arcpy의 어느 곳에서나 모든 ArcObject를 노출시키는 COM 바인딩이 없습니다.
Jason Scheirer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.