Puede escribir un script de Python para ejecutar y usar una herramienta web o un servicio de geoprocesamiento de varias formas. La forma principal de ejecutar una secuencia de comandos es usar ArcPy. ArcPy tiene métodos integrados a los que conectarse y con los que ejecutar y manejar el resultado de un servicio. De manera alternativa, para acceder al servicio desde API REST de ArcGIS, utilice módulos integrados de Python para realizar las llamadas REST usando una estructura JSON para transferir los resultados. Debe crear un cliente desde cero con código de Python para usarlo. La mayor parte de los scripts se conectarán a y utilizarán los servicios de geoprocesamiento a través de ArcPy.
Nota:
Los siguientes ejemplos consumen un servicio de geoprocesamiento en un ArcGIS Server federado. Nunca utiliza el elemento de herramienta web correspondiente del portal en Python.
Uso de ArcPy
Se puede acceder a una herramienta web a través de la ventana de Python en ArcGIS Pro, una herramienta de secuencia de comandos o una secuencia de comandos independiente. La función ImportToolbox utiliza una URL de servicio y otros valores para conectarse y utilizar una herramienta web.
Ejemplo: Conectarse a un servicio utilizando ImportToolbox con una URL SOAP, un servicio en una carpeta, con nombre de usuario y contraseña.
arcpy.ImportToolbox("https://organization.example.com/<context>/services;GPFolder/BufferService;serverusername;serverpassword")
Una herramienta web o servicio de geoprocesamiento se puede ejecutar de forma sincrónica o asíncrona. Como creador de scripts de Python, debe entender cómo se ejecuta el servicio para utilizarlo. La propiedad IsSynchronous se utiliza para determinar si un servicio se ejecuta de forma sincrónica o asincrónica. Cuando un servicio de ejecuta de forma sincrónica, los resultados se devuelven automáticamente, pero no es posible emprender acciones hasta que se ha completado. Cuando un servicio se ejecuta de forma asincrónica, el estado actual debe consultarse periódicamente. Una vez finalizado el servicio, podrá acceder al resultado.
El siguiente código de Python muestra cómo conectarse a un servicio de geoprocesamiento asíncrono. El código utiliza funciones de ArcPy para ejecutar el servicio, obtener el resultado y seguir procesándolo. Al establecer una variable de resultado cuando se ejecuta la tarea, se puede utilizar un bucle while para verificar el estado del objeto Result. La tarea ha terminado una vez que devuelve un código de estado de 4 (logrado) o superior.
Use un servicio asíncrono para crear una zona de influencia y guardar el resultado a nivel local.
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')
Utilizar el extremo REST
Una forma alternativa de utilizar una herramienta web es escribir una secuencia de comandos que realice llamadas REST, utilizando JSON como formato de intercambio de datos. Este enfoque requiere escribir código para enviar la solicitud y gestionar la respuesta.
Enviar y recibir mensajes REST es más complejo, puesto que debe gestionar todos los aspectos de la sintaxis de entradas y salidas. Al enviar y recibir mensajes REST, se devuelven de forma coherente. Una petición puede ser enviada a través de un método HTTP GET o HTTP POST y una respuesta puede volver estructurada como JSON.
El ejemplo siguiente muestra cómo enviar una solicitud y gestionar una respuesta.
Enviar la solicitud
Por ejemplo, hay un servicio de geoprocesamiento para crear cuencas visuales accesible desde https://organization.example.com/<context>/rest/services/Elevation. Este servicio toma un punto y una distancia como entrada y devuelve un conjunto de entidades. Las siguientes entradas se pueden utilizar para comprender mejor el servicio:
Nombre del parámetro | Valor de entrada |
---|---|
Punto de observación de entrada (GPFeatureRecordSetLayer) | {"geometryType": "esriGeometryPoint", "spatialReference": {"wkid": 54003}, 'features':[{'geometry': {'x': -13308192.1956127, 'y': 4221903.58555983}}]} |
Distancia de cuenca visual (GPLinearUnit) | {'distance': 8.5, 'units': 'esriMiles'} |
Formato (el formato de la salida) | JSON |
Esta petición devuelve el JSON de las ubicaciones visibles desde el servicio. La dirección URL completa utilizada para generar la solicitud se puede utilizar en la barra de direcciones del navegador 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
La dirección URL se puede presentar utilizando el módulo de Python urllib o urllib2. El siguiente código de Python ejecuta la petición mencionada de una forma similar a utilizar el Directorio de servicio o copiar el vínculo en la barra de direcciones del navegador 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')))
El objeto Result se devuelve como una cadena de caracteres. Pueden usarse varios métodos para realizar una solicitud y analizar un resultado; el ejemplo anterior es solo uno de ellos. El JSON devuelto desde una herramienta web se puede insertar en un diccionario utilizando json.loads(). Dependiendo de la salida de la herramienta web, esta podría ser la mejor técnica, o podría necesitar explorar otras opciones para tratar la salida cuando se consume desde Python a través de REST.
Nota:
Cuando trabaje con entidades de resultado, asegúrese de que utilizar los pares x,y reales tiene sentido para su flujo de trabajo, puesto que no recibirá las entidades reales en un formato que admita la geometría mediante ArcPy.
Un servicio que se ejecuta de forma asíncrona requiere que compruebe periódicamente el estado de la tarea para ver si ha finalizado, como en el ejemplo anterior con ArcPy. El código Python podría buscar la frase esriJobSucceeded o esriJobFailed en el mensaje de estado jobStatus, que se devuelve al comprobar el estado del trabajo. La siguiente muestra de código presenta una técnica para trabajar con una herramienta asíncrona (utilizando 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")