Usar herramientas web en secuencias de comandos de Python

Puede escribir una secuencia de comandos de Python para ejecutar y usar una herramienta web 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 del servicio. De manera alternativa, si accede al servicio desde el Directorio de servicios de ArcGIS Server, puede utilizar módulos integrados de Python para realizar las llamadas REST usando una estructura JSON para transferir los resultados. Deberá crear un cliente desde cero con el código Python para usarlo. La mayor parte de las secuencias de comandos se conectarán a y utilizarán los servicios de geoprocesamiento a través de ArcPy.

Nota:

Los ejemplos que se proporcionan aquí consumen el servicio de ArcGIS Server. No se consume la herramienta web desde el portal.

Usar 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 dirección URL del servicio se utiliza para conectar y utilizar una herramienta web.

Conéctese a un servicio usando ImportToolbox.

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

La ruta utilizada para importar la herramienta es la dirección URL de la herramienta web. ImportToolbox acepta dos parámetros la dirección URL del servicio y un alias opcional para la caja de herramientas. El parámetro de la dirección URL está dividido en dos partes separadas por un punto y coma (;). La primera parte es la dirección URL (o vínculo) para el extremo final del servicio y la segunda es el nombre del servicio (de forma opcional, un nombre de carpeta precede al nombre de servicio).

Una herramienta web se puede ejecutar de forma sincrónica o asíncrona. Como scripter de Python, necesita entender cómo se ejecuta el servicio para utilizarlo. La propiedad IsSynchronous se puede utilizar para determinar el tipo de ejecución de un servicio. 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. Para servicios asíncronos, el estado actual de la ejecución debe consultarse periódicamente. Una vez que haya terminado de ejecutarse el servicio, se puede acceder al resultado.

El siguiente código Python muestra cómo conectarse a un servicio de geoprocesamiento asíncrono, y con las funciones ArcPy, ejecutarlo, obtener el resultado y procesarlo. Al establecer una variable de resultado cuando se ejecuta la tarea, se puede utilizar un bucle while para verificar el estado. 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("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')

Más información sobre el objeto Result y los códigos de estado, así como sobre la creación de una salida ráster y de imagen de mapa, está disponible en el tema de la Ayuda Utilizar herramientas en Python.

Usar REST

Una forma alternativa (pero menos habitual) de utilizar una herramienta web es escribir una secuencia de comandos que realice llamadas REST, utilizando JSON como formato de intercambio de datos. Este método requiere que el usuario escriba el código para enviar la solicitud y gestionar la respuesta.

Enviar y recibir mensajes REST está más implicado, puesto que debe tratar todos los aspectos de las entradas y salidas de la sintaxis usted mismo. 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 núcleo de las bibliotecas Python permite enviar tanto una solicitud como funciones, lo que facilita la lectura y el análisis de los mensajes JSON.

El siguiente ejemplo utiliza un servicio en los servidores de muestra de Esri y demuestra cómo puede conectarse al servicio, enviar una solicitud y manejar una respuesta.

Enviar la solicitud

Por ejemplo, SampleServer6 contiene un servicio de geoprocesamiento para crear cuencas visuales y es accesible desde http://sampleserver6.arcgisonline.com/ArcGIS/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 de parámetroValor 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 (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.

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

La dirección URL se puede presentar utilizando el módulo de Python urllib o urllib2. El siguiente código Python ejecutará 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.

# 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')))

El objeto Result se devuelve como una cadena de caracteres. Hay una serie de métodos diferentes que se pueden utilizar para realizar una solicitud y analizar un resultado; el ejemplo anterior es sólo un método. Los JSON devueltos desde una herramienta web se pueden insertar en un diccionario utilizando json.loads() como se muestra en el ejemplo anterior. 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:

Si está trabajando con entidades de resultado, asegúrese de que utilizar los pares x,y reales tiene sentido para su flujo de trabajo, puesto que no va a recibir las entidades reales en un formato que admita la geometría en ArcGIS.

Un servicio que se ejecuta de forma asíncrona requiere que se pregunte 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 = "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")

Temas relacionados


En este tema
  1. Usar ArcPy
  2. Usar REST