Python スクリプトでのジオプロセシング サービスの使用

Python スクリプトを作成して、ジオプロセシング サービスを複数の方法で実行および利用できます。スクリプトを実行する主な手段は ArcPy の使用です。ArcPy には、サービスからの結果に接続し、実行して処理するメソッドが組み込まれています。代わりに、Services Directory を使用すると、組み込みの Python モジュールを使って、JSON 構造を使用した REST 呼び出しを行い、結果を転送することができます。この方法を利用するには、Python コードによってクライアントを最初から構築する必要があります。スクリプトの大部分は、ArcPy を介してジオプロセシング サービスに接続し使用します。

ArcPy 方式

ジオプロセシング サービスには、ArcMap の [Python] ウィンドウ、スクリプト ツール、またはスタンドアロン スクリプトを使用してアクセスできます。ジオプロセシング サービスに接続して使用するには URL が使用されます。

ImportToolbox を使用してサービスに接続します。

# arcpy.ImportToolbox("http://<hostname>:<port>/arcgis/services;<optional folder>/<service name>","<optional alias>")

arcpy.ImportToolbox("http://degrassi:6080/arcgis/services;GPFolder/BufferService","PointAlias")

ツールのインポートに使用されるパスはジオプロセシング サービスの URL です。 ImportToolbox は、2 つのパラメータ(サービスへの URL とツールボックスのオプションのエイリアス)を受け入れます。URL パラメータはセミコロン(;)で 2 つの部分に区切られます。最初の部分はサービス エンド ポイントへの URL(リンク)であり、次の部分はサービス名(オプションで、サービス名の前にフォルダ名が付加される)です。

ジオプロセシング サービスは同期または非同期のいずれかの方法で実行されます。Python スクリプトを使用するには、ユーザは、サービスの実行方法を理解している必要があります。サービスの実行方法を判断するには、IsSynchronous プロパティを使用できます。サービスが同期して実行されている場合、結果は自動的に返されますが、サービスが完了するまで他のアクションを行うことはできません。非同期サービスの場合は、現在の実行ステータスを定期的に照会する必要があります。サービスの実行が完了すると、結果へのアクセスが可能になります。

次の Python コードは、非同期ジオプロセシング サービスに接続し、ArcPy 関数を使用してサービスを実行し、結果を取得してその結果をさらに処理する方法を示しています。タスクの実行時に result 変数を設定することで、while ループをステータスの確認に使用できます。タスクは、ステータス コード 4(succeeded)以上が返されると終了します。

非同期 GP サービスを使用して、バッファを作成し、結果をローカルに保存します。

import arcpy
import time

arcpy.ImportToolbox("http://sampleserver1.arcgisonline.com/ArcGIS/services;Elevation/ESRI_Elevation_World", "viewshedAlias")

result = arcpy.Viewshed_viewshedAlias(r'c:\data\inputPoint.shp', "10000 Kilometers")

while result.status < 4:
	   print result.status
	   time.sleep(0.2)
print "Execution Finished"

result.getMessages()
arcpy.CopyFeatures_management(result.getOutput(0), 'localResult.shp')

result オブジェクトとステータス コード、およびラスタとマップ イメージ出力の作成に関する詳細については、「Python でのツールの使用」ヘルプ トピックをご参照ください。

RESTful 方式

ジオプロセシング サービスを使用するもう 1 つの方法(ただし、使用頻度は少ない)は、データ交換形式として JSON を使用して REST 呼び出しを行うアプリケーションの構築です。このメソッドでは、ユーザが、リクエストの送信と応答の処理の両方についてコードを記述する必要があります。

REST メッセージの送受信がより深く関与することになり、ユーザは入出力構文のすべての内容を自分自身で処理しなければなりません。REST メッセージを送受信するメリットは、それらのメッセージが一貫した方法で返される点にあります。リクエストは、HTTP GET メソッドを介して送信でき、応答は、JSON として構造化して返すことができます。コア Python ライブラリは、HTTP GET リクエストと関数の送信を両方ともサポートしているため、JSON メッセージの読み取りと解析が容易になっています。

次の例では、Esri サンプル サーバ上のサービスを使用します。そのサービスに接続し、リクエストを送信し、応答を処理する方法を示します。

リクエストの送信

たとえば、SampleServer1 は、可視領域を作成するジオプロセシング サービスを保持し、http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation からアクセスできます。このサービスはポイントと距離を入力として受け取り、フィーチャ セットを返します。サービスをさらに理解するために、次の入力を使用できます。

パラメータ名

入力値

入力観測ポイント(GPFeatureRecordSetLayer)

{"geometryType" : "esriGeometryPoint", "spatialReference" : {"wkid" : 54003}, 'features':[{'geometry':{'x': -13308192.1956127, 'y':  4221903.58555983}}]}

可視領域距離(GPLinearUnit)

{ 'distance' : 8.5, 'units' : 'esriMiles' }

フォーマット(出力のフォーマット)

JSON

このリクエストでは、サービスから見通せる場所の JSON が返されます。リクエストの生成に使用される完全 URL は、Web ブラウザのアドレス バーで使用できます。

http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed/execute?Input_Observation_Point={%22features%22%3A[{%22geometry%22%3A{%22x%22%3A-13308192.1956127%2C%22y%22%3A4221903.58555983}}]}&Viewshed_Distance={+%27distance%27+%3A+8.5%2C+%27units%27+%3A+%27esriMiles%27+}&env%3AoutSR=&env%3AprocessSR=&f=pjson

この URL は、Python モジュール urllib または urllib2 を使用して送信できます。次の Python コードは、Service Directory を使用するか、リンクを Web ブラウザのアドレス バーにコピーした場合と同様な方法で上記のリクエストを実行します。

import urllib
import json

inPts = {"geometryType" : "esriGeometryPoint",
         "spatialReference" : {"wkid" : 54003},
         'features':[{'geometry':{'x': -13308192.1956127,'y':  4221903.58555983}}]}
dist = {'distance':8.5,'units':'esriMiles'}

data = {'Input_Observation_Point': inPts,
        'Viewshed_Distance': dist,
        'f': 'pjson'}

URL  = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed/execute'

result = urllib.urlopen(URL, urllib.urlencode(data)).read()
print json.loads(result)

結果のオブジェクトは文字列として返されます。リクエストの作成と結果の解析に使用できる多数の異なるメソッドが用意されており、上記の例は、メソッドの 1 つを示しています。ジオプロセシング サービスから返される JSON は、上記の例のように json.loads() を使用してディレクトリに配置できます。ジオプロセシング サービスの出力によっては、これが最適な手法であることもあれば、REST を介して Python から利用される場合のジオプロセシング サービスからの出力を処理するために、他のオプションを検討する必要があることもあります。

注意注意:

結果のフィーチャを操作するときは、実際の XY 座標ペアの使用がワークフローで機能していることを確認してください。この理由は、実際のフィーチャは、ArcGIS 内でジオメトリをサポートするフォーマットでは受信されないからです。

非同期で実行されるサービスの場合は、ArcPy を使用した上記の例と同様に、定期的にタスクのステータスを要求して、タスクが終了したかどうかを確認する必要があります。Python コードにより、jobStatus ステータス メッセージ内のフレーズ esriJobSucceeded または esriJobFailed を探すことができます。これらのフレーズは、ジョブ ステータスの確認時に返されます。次のサンプル コードは、非同期ジオプロセシング サービスを操作する手法の 1 つ(submitJob を使用)を示しています。

import urllib, json, time
    
inPts = {"geometryType" : "esriGeometryPoint",
         "spatialReference" : {"wkid" : 54003},
         'features':[{'geometry':{'x': -13308192.1956127,'y':  4221903.58555983}}]}
dist = {'distance':8.5,'units':'esriMiles'}

data = {'Input_Observation_Point': inPts,
        'Viewshed_Distance': dist,
        'f': 'pjson'}

taskUrl = "http://localhost:6080/arcgis/rest/services/WorldViewshed/GPServer/viewshed"
submitUrl = taskUrl + "/submitJob"

submitResponse = urllib.urlopen(submitUrl, urllib.urlencode(data))   
submitJson = json.loads(submitResponse.read())    

if 'jobId' in submitJson:  
    jobID = submitJson['jobId']        
    status = submitJson['jobStatus']        
    jobUrl = taskUrl + "/jobs/" + jobID            
        
    while status == "esriJobSubmitted" or status == "esriJobExecuting":
        print "checking to see if job is completed..."
        time.sleep(1)
        
        jobResponse = urllib.urlopen(jobUrl, "f=json")     
        jobJson = json.loads(jobResponse.read())
     
        if 'jobStatus' in jobJson:  
            status = jobJson['jobStatus']            
         
            if status == "esriJobSucceeded":                                        
                    if 'results' in jobJson:
                        resultsUrl = jobUrl + "/results/"
                        resultsJson = jobJson['results']
                        for paramName in resultsJson.keys():
                            resultUrl = resultsUrl + paramName                                        
                            resultResponse = urllib.urlopen(resultUrl, "f=json")   
                            resultJson = json.loads(resultResponse.read())                            
                            print resultJson     
                
            if status == "esriJobFailed":                                        
                    if 'messages' in jobJson:                        
                        print jobJson['messages']
                                           
else:
    print "no jobId found in the response"

Python、ArcPy およびスクリプト ツールの概要

Python、ArcPy およびスクリプト ツールを使い慣れていない方は、下の表に記載した、使用開始にあたって参考になるトピックをご参照ください。

ヘルプ トピック

コンテンツ

カスタム ツール作成の概要

独自のプロセシング ツール作成の基本概要

Python とは

ArcPy とは

Python および ArcPy の入門トピック。これらのトピックでは、Python および ArcPy サイト パッケージの詳細を説明しています。

Python でのツールの作成の概要

スクリプト ツールとは

Python を使用したカスタム スクリプト ツール作成の入門トピック。

スクリプト ツール パラメータの設定

このトピックでは、スクリプト ツール パラメータの定義方法を詳しく説明しているため、スクリプト ツール作成プロセスを学習した後に参照する機会が多くなります。

関連トピック

6/13/2014