Vous pouvez écrire un script Python pour exécuter et utiliser un outil Web ou un service de géotraitement de plusieurs façons. Le principal mode d’exécution d’un script consiste à utiliser ArcPy. ArcPy possède des méthodes intégrées permettant de se connecter à un service, de l’exécuter et d’en traiter le résultat. Pour accéder au service à partir d’ArcGIS REST API, vous pouvez également utiliser des modules Python intégrés afin d’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 ci-dessous utilisent un service de géotraitement sur un ArcGIS Server fédéré. Vous n’utilisez jamais l’élément d’outil Web correspondant dans Python.
Utiliser ArcPy
Un outil Web est accessible via la fenêtre Python dans ArcGIS Pro, un outil de script ou un script autonome. La fonction ImportToolbox utilise l’URL d’un service ainsi que d’autres valeurs pour se connecter à un outil Web et de l’utiliser.
Exemple : se connecter à un service à l’aide de la fonction ImportToolbox avec une URL SOAP, un service dans un dossier, avec un nom d’utilisateur et le mot de passe associé.
arcpy.ImportToolbox("https://organization.example.com/<context>/services;GPFolder/BufferService;serverusername;serverpassword")
Un outil Web ou 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 permet de déterminer si un service s’exécute de manière synchrone ou asynchrone. Lorsqu’un service s’exécute de manière synchrone, les résultats sont renvoyé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 doit être interrogé à intervalles réguliers. Une fois le service terminé, vous avez accès au résultat.
Le code Python suivant illustre le mode de connexion à un service de géotraitement asynchrone. Le code utilise les fonctions ArcPy pour exécuter le service, obtenir le résultat et lui appliquer d’autres traitements. En définissant une variable de résultat lors de l’exécution de la tâche, il est possible de faire appel à une boucle while pour vérifier l’état de l’objet Result. 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("https://organization.example.com/<context>/services;Elevation/viewshedAlias;serverusername;serverpassword")
result = arcpy.viewshedAlias.Viewshed(r'c:\data.gdb\inputPoint', "10000 Kilometers")
while result.status < 4:
print(result.status)
time.sleep(0.2)
print("Tool finished")
print(result.getMessages())
arcpy.management.CopyFeatures(result, r'c:\results.gdb\result')
Utiliser le point de terminaison REST
Une méthode alternative d’utilisation d’un outil Web consiste à écrire un script qui effectue des appels REST, avec JSON comme format d’échange de données. Cette approche 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 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 HTTP GET ou HTTP POST, et la réponse revient structurée au format JSON.
L’exemple suivant illustre la façon d’envoyer d’envoyer une requête et de traiter une réponse.
Envoyer la requête
Par exemple, un service de géotraitement destiné à créer des champs de vision est accessible à partir de https://organization.example.com/<context>/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 de paramètre | Valeur 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.
https://organization.example.com/<context>/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.
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 = 'https://organization.example.com/<context>/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. Diverses 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 outil Web peut être placé dans un dictionnaire à l’aide de json.loads(). Selon la sortie de l’outil Web, 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 les entités de résultat, assurez-vous qu’il est pertinent de recourir à des paires x,y dans le cadre de votre processus, car vous ne recevrez pas les entités dans un format prenant en charge la géométrie dans ArcPy.
Un service qui s’exécute de manière asynchrone nécessite que vous vérifiez régulièrement 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 outil Web 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 = "https://organization.example.com/<context>/rest/services/Elevation/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")
Rubriques connexes
Vous avez un commentaire à formuler concernant cette rubrique ?