PythonからArcObjectsにアクセスしますか?


132

arcgisscriptingまたはArcPy を介して公開されていないもののスクリプトを作成したいと思います。

PythonからArcObjectsにアクセスするにはどうすればよいですか?


3
本番環境でこれらの方法を使用することについて考えている人はいますか?数年前、UCで私はほとんどのPythonモジュールを書くESRI C ++開発者の1人と話をしましたが、彼は本番環境で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 ++開発者の観点からは、個別のものがあります。彼らは、使用のVisual Studio(はいExpressは OKです)とWindowsのSDKをただのArcGIS、Pythonとcomtypesが十分である、が、これらは必須ではありません。

スニペットモジュールの取得

* 10.1以降の場合automation.py、comtypesモジュールを少し変更する必要があることに注意してください10.1のArcObjects + comtypesを参照してください。


次のステップ

...または:頭がおかしくなった?C#コードの例を見ると目が泳いでいるように見えますが、クレーンのように思えないかもしれません。ここを見て:


10
このスレッドは私の注目を集めており、いくつかの誤解が浮かんでいるようです。PythonでArcObjectsを使用するために、Visual StudioまたはMIDLコンパイラは必要ありません。必要なのはcomtypesパッケージだけです。私のプレゼンテーションには、Pythonを使用してCOMコンポーネントを作成するための高度な演習が含まれていましたが、それはUberPyGeeksを対象としたものでした。snippets.pyファイルには、必要なすべての例が含まれています。

1
@マーク、訂正してくれてありがとう。明確にするために、上記のレシピでは、ctypesが既にインストールされている限り、ステップ1、3、4を削除できますか?
マットウィルキー

2
うん。ラボでテストしました。あなただけのcomtypesをインストールする必要があります。
RK

@RK、素晴らしい!検証していただき、回答を最新のものにしていただきありがとうございます。
マットウィルキー

1
スニペットモジュールは、インストール可能なaoモジュールとしてリキャストします:github.com/maphew/arcplus/tree/master/arcplus/ao(10.3に更新されました。10.2のファイルの以前のバージョンを参照してください)。いくつかのバグが解消されると、メインの回答が更新されます。
マットウィルキー

32

はい、マット・ウィルキーが上で言及したマーク・セダーホルムのプレゼンテーションは、始めるのに最適な場所です。Mattが提示するレシピ/コードは確かに滑らかで、おそらく物事を進めるための最良の方法です。ただし、ArcGIS 10.0で使用しているブルートフォース方式について言及したかったのです。この方法で実行する自動化スクリプト(スタンドアロン、アプリケーション境界外)がいくつかあり、それらは正常に動作します。ただし、最大速度が懸念される場合は、Mattのソリューションを使用して完了できます。

comtypesパッケージを使用して、すべてのArcObjectsライブラリ(* .olb)を強制的にラップします。これにより、PythonはすべてのArcObjectsにアクセスできます。ESRIフォーラムに投稿しフランクパークスからラッピングコードを入手しました。基本的に同じことをする独自のコードがありましたが、肥大化しただけで機能的でしたが、彼の方がずっときれいでした。そう:

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オブジェクトから始まるArcObjectsへのフルアクセスが必要です。私の経験では、最初の実行でのArcObjectsライブラリのラッピングは好ましくないほど遅くなく、その後の実行ではラッピングは発生しません。ライブラリはすでにラップおよびコンパイルされているため、処理ははるかに高速です。

追加: これには大きな注意が必要です。ここで指定するNewObj関数は、Pythonスクリプトがインプロセスで実行されていることを前提としています。そうでない場合、この関数はPythonプロセスでオブジェクトを作成し(アウトプロセス)、オブジェクト参照が間違っています。外部Pythonスクリプトからインプロセスオブジェクトを作成するには、IObjectFactoryを使用する必要があります。詳細については、このstackexchangeの投稿でKirk Kuykendallのコメントとヒントを参照してください。


1
このアプローチの良い点は、Visual Studioをインストールする必要がないことです。VisualStudioをインストールする必要がないのは、comオブジェクトを登録することだけだとすればかなり重いです。この純粋なpythonメソッドについて知っていれば、Cederholmのルートを試したことはないでしょう。;-)
マットウィルキー

1
この答えでこの概念を少し拡張し、インポートを行い、タイプライブラリを1ステップのプロセスにラップしました。gis.stackexchange.com
5017

20

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

基本的な手順は次のとおりです。

  1. Pythonのパフォーマンスに問題があると思われるコアロジックの一部をC ++で記述します。
  2. システムコンパイラ(nmake、makeなど)を使用して、コアファイル(この場合はArcObject C ++ APIメソッド呼び出しを使用)をオブジェクトファイルから共有(.so)または動的ライブラリ(.dll)にコンパイルします。
  3. PythonクラスとC ++メソッドシグネチャの間にctypesマッピングを記述します[SWIGはこれを自動化しようとしますが、クレイジーなオブジェクトタイプを使用していても簡単です]
  4. コンパイルされたライブラリをPythonプログラムにインポートし、バインドされたクラス/メソッドバインディングを他のPythonクラスと同様に使用します!

これはおそらく、Python内からC / C ++コードを参照するより一般的な方法です。COMオブジェクトを処理する必要がない場合、長期的にはおそらくより簡単になるでしょう。また、リンクされたライブラリオブジェクトのコンパイルにシステム固有の機能をすべて許可します(したがって、Pythonはsystem / python実装固有ではありません)。


3
これは、ArcObjectsを操作するための最良の方法です。comtypesの使用はプロトタイピングに最適ですが、独自のC拡張機能を作成すると、C ++ / Pythonオブジェクトバリアをあまり超えないため、優れたPythonicデザイン(考えなければならないため)とパフォーマンスの向上につながります。実用的な目的のために、これは設計/開発/デバッグするのが難しいので、迅速で汚れたものは窓から消えます。
ジェイソンScheirer

18

もう1つのオプションは、Python for .NETを使用することです。これは非常に簡単に設定でき、ArcObjectsを含むすべての.NET DLLで動作します。

インプロセスオブジェクトに関する問題は発生していません。ArcMapのインスタンスを開き、レイヤーを追加および操作することで問題なく動作しました。

唯一の要件は、Python for .NETライブラリを含むフォルダーと、Pythonの標準インストールです。

詳細とサンプルスクリプトこちら。サンプルスクリプトは、http://gist.github.com/923954から直接見ることもできます。

残念ながら、これはローカル開発マシンでは問題なく動作しますが、他の場所に展開するにはArcObjects SDKとVisual Studio(無料のExpressエディションを含む)をインストールする必要があります。ArcObject .NET DLLの展開を参照してください


レシピは明快で明快で、よく提示されています。ありがとうGeographika!回答に最小限のスクリプトスニペットを含めることをお勧めします。そうすることで、サイトが改修された場合に回答が単独で立つことができます。
マットウィルキー

1
それはまさにこの古いブログ投稿(gissolved.blogspot.com/2009/06/python-toolbox-3-pythonnet.html)で行ったことであり、期待どおりに動作しますが、Pythonスクリプトが理解できる結果(文字列、数字または無効)。
サミュエル


5

他の回答で言及されていない1つのアプローチは、arcpyライブラリ自体が使用するのと同じ方法を使用することです。たとえば、C:\ Program Files \ ArcGIS \ Desktop10.0 \ arcpy \ arcpy \ cartography.pyでは、いくつかのfixargsおよびオブジェクト変換関数を使用してPythonがArcObjectsツールを呼び出しています。

コードには「TRADE SECRETS:ESRI PROPRIETARY AND CONFIDENTIAL」と書かれているため、ここに投稿しても大丈夫ではありません。ただし、ウェブ上の他の場所にもあります。とにかく、これはSimplifyBuilding_cartography()comtypeや他の追加ライブラリをインストールせずに関数を呼び出す比較的簡単な方法のように見えます。

編集:

以下のジェイソンのコメントを参照してください。上記を行うことはあまりあなたを買わないように聞こえます。


私も気づきましたが、あまりにも多くのブードゥー教徒のようです。
blah238

1
完全に公開されたアークオブジェクトのセットを呼び出していません。
ジェイソンシャイラー

@JasonScheirer、それはそうかもしれないが、それは明らかに、まっすぐなarcpy APIよりもArcObjects(私が思うに)へのより大きな程度のアクセスを許可し、別のライブラリのインストールを必要としないという利点がある。他の人が使用するツールを開発している場合、後者は重要です。この方法で何にアクセスできるのかを完全に知りたいのですが、特定の目的には十分かもしれません。(ただし、今は確認できません-会社のLANにはいません。)
LarsH

1
事実ではないことを保証できます。私はそれの多くを開発しました。
ジェイソンシャイラー

1
できません。この場合、「ArcObject」は少し間違った呼び名です。基になるオブジェクトに到達する方法はなく、arcgisscripting / arcpyのすべてのArcObjectsを公開するCOMバインディングはありません。
ジェイソンシャイラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.