Utiliser des services de géotraitement dans des scripts Python

Vous pouvez écrire un script Python pour exécuter et utiliser un service de géotraitement de plusieurs façons. La principale méthode d'exécution d'un script consiste à utiliser ArcPy. ArcPy possède des méthodes intégrées permettant de se connecter au service, de l'exécuter et d'en traiter le résultat. Vous pouvez également, si vous accédez au service à partir du répertoire de services ArcGIS Server, utiliser des modules Python intégrés pour effectuer des appels REST à l’aide d’une structure JSON et transférer les résultats. Vous devez créer un client intégralement à l’aide de code Python pour exploiter cette fonction. La majorité des scripts se connecte à des services de géotraitement et les utilise par le biais d'ArcPy.

Remarque :

Les exemples donnés ici utilisent le service ArcGIS Server réel. Vous n’utilisez pas le service de géotraitement depuis le portail.

Utiliser ArcPy

Un service de géotraitement est accessible via la fenêtre Python dans ArcGIS Pro, un outil de script ou un script autonome. L’URL du service permet de se connecter à un service de géotraitement et de l’utiliser.

Se connecter à un service avec ImportToolbox.

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

Le chemin utilisé pour importer l’outil est l’URL du service de géotraitement. ImportToolbox accepte deux paramètres : l'URL du service et un alias facultatif pour la boîte à outils. Le paramètre d'URL est divisé en deux parties, séparées par un point-virgule (;). La première partie est l’URL (ou lien) vers l’extrémité du service, et la seconde est le nom du service (en option, le nom du dossier précède le nom du service).

Un service de géotraitement peut s’exécuter de manière synchrone ou asynchrone. En tant que créateur de script Python, vous devez comprendre comment le service s’exécute pour pouvoir l’utiliser. La propriété IsSynchronous peut servir à déterminer le type d'exécution d'un service. Lorsqu'un service s'exécute de manière synchrone, les résultats sont retournés automatiquement, mais aucune autre action ne peut être effectuée avant la fin de son exécution. Pour les services asynchrones, l'état actuel de l'exécution doit être interrogé périodiquement. Une fois l'exécution du service terminée, le résultat est accessible.

Le code Python suivant illustre la connexion à un service de géotraitement asynchrone, et la façon dont les fonctions ArcPy l’exécutent, obtiennent le résultat et lui appliquent d’autres traitements. En définissant une variable de résultats lors de l'exécution de la tâche, il est possible de faire appel à une boucle while pour vérifier l'état. La tâche est terminée lorsqu'un code d'état de 4 (réussite) ou supérieur est renvoyé.

Utilisez un service asynchrone pour créer une zone tampon et enregistrer le résultat localement.

import arcpy import time
arcpy.ImportToolbox("http://sampleserver6.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")
print(result.getMessages())
arcpy.CopyFeatures_management(result[0], 'localResult.shp')

Des informations supplémentaires concernant les codes d'objet et d'état Result, ainsi que la création d'une sortie raster et d'image de carte, sont disponibles dans la rubrique d'aide Utilisation d'outils dans Python.

Utiliser REST

Une méthode alternative (mais moins courante) d’utilisation d’un service de géotraitement consiste à écrire un script qui effectue des appels REST, avec JSON comme format d’échange de données. Cette méthode implique d'écrire du code pour envoyer la requête et traiter la réponse.

L'envoi et la réception de messages REST est plus contraignant, car vous devez gérer vous-même tous les aspects de la syntaxe des entrées et des sorties. Lors de l'envoi et de la réception de messages REST, ils sont renvoyés de manière cohérente. Il est possible d'effectuer les envois via une méthode GET HTTP ou HTTP POST, et la réponse peut revenir structurée au format JSON. Les principales bibliothèques Python prennent en charge l'envoi d'une requête et de fonctions, ce qui simplifie la lecture et l'analyse de messages JSON.

L'exemple qui suit utilise un service sur les serveurs exemple Esri et illustre la façon de se connecter au service, d'envoyer une requête ou de traiter une réponse.

Envoyer la requête

Par exemple, SampleServer6 contient un service de géotraitement destiné à créer des champs de vision ; il est accessible à partir de http://sampleserver6.arcgisonline.com/ArcGIS/rest/services/Elevation. Ce service prend un point et une distance comme entrée et renvoie un jeu d'entités. Les entrées suivantes permettent de mieux comprendre le service :

Nom du paramètreValeur en entrée

Point d'observation en entrée (GPFeatureRecordSetLayer)

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

Distance du champ de vision (GPLinearUnit)

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

Format (format de la sortie)

JSON

Cette requête renvoie le format JSON des emplacements visibles à partir du service. L'URL complète permettant de générer la requête peut être utilisée dans la barre d'adresse d'un navigateur Web.

http://sampleserver6.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

Il est possible d'envoyer l'URL à l'aide du module Python urllib ou urllib2. Le code Python suivant exécute la requête ci-dessus, ce qui revient à utiliser un répertoire de service ou à copier un lien dans la barre d'adresse d'un navigateur Web.

# Requires Python 3+
import urllib.request as urlopen import urllib.parse as urlencode import urllib.request as request 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://sampleserver6.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed/execute'
req = request.Request(URL, urlencode.urlencode(data).encode('UTF-8')) response = urlopen.urlopen(req) response_bytes = response.read()
print(json.loads(response_bytes.decode('UTF-8')))

L'objet Result est renvoyé sous forme de chaîne. Plusieurs méthodes peuvent être utilisées pour effectuer une requête et analyser un résultat ; l’exemple ci-dessus illustre l’une d’entre elles. Le JSON renvoyé par un service de géotraitement peut être placé dans un dictionnaire à l’aide de json.loads(), comme illustré dans l’exemple précédent. Selon la sortie de votre service de géotraitement, cette technique peut s’avérer la meilleure, ou vous pouvez avoir besoin d’expérimenter d’autres solutions pour traiter la sortie lorsqu’il est utilisé depuis Python via REST.

Remarque :

Si vous utilisez des entités de résultat, veillez à recourir aux paires x,y, utiles à votre processus, car vous ne recevrez pas les entités dans un format prenant en charge la géométrie dans ArcGIS.

Un service qui s'exécute de manière asynchrone nécessite que vous demandiez régulièrement quel est l'état d'une tâche, pour savoir si elle est terminée, comme dans l'exemple ci-dessus avec ArcPy. Votre code Python peut rechercher l'expression esriJobSucceeded ou esriJobFailed dans le message d'état jobStatus renvoyé lors de la vérification de l'état de la tâche. L’exemple de code suivant présente une technique d’utilisation d’un service de géotraitement asynchrone (à l’aide de submitJob).

import urllib.request as urlopen import urllib.parse as urlencode import urllib.request as request import json import time
def sendReq(URL, data=None):
    req = request.Request(URL, urlencode.urlencode(data).encode('UTF-8'))    response = urlopen.urlopen(req)    response_bytes = response.read()    return json.loads(response_bytes.decode('UTF-8'))
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"
submitJson = sendReq(submitUrl, data)
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)
        jobJson = sendReq(jobUrl, {"f": "json"})
        if 'jobStatus' in jobJson.keys():
            status = jobJson['jobStatus']
            if status == "esriJobSucceeded":
                if 'results' in jobJson:
                    resultsJson = jobJson['results']                    for paramName in resultsJson.keys():
                        resultsUrl = jobUrl + "/" + resultsJson[paramName]['paramUrl']                        resultJson = sendReq(resultsUrl, {"f": "json"})                        print(resultJson)
            if status == "esriJobFailed":
                if 'messages' in jobJson.keys():
                    print(jobJson['messages'])
else:
    print("no jobId found in the response")

Dans cette rubrique
  1. Utiliser ArcPy
  2. Utiliser REST