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 la API REST de ArcGIS, puede utilizar 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. No se consume el elemento de herramienta web correspondiente del portal.

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

Conéctese a un servicio usando ImportToolbox o AddToolbox.

# arcpy.ImportToolbox("https://machine.domain.com/webadaptor/services;<optional folder>/<service name>;{username};{password}")
arcpy.ImportToolbox("https://machine.domain.com/webadaptor/services;GPFolder/BufferService;serverusername;serverpassword")

La ruta utilizada para importar la herramienta es la dirección URL de la herramienta web. ImportToolbox and AddToolbox acepta la información del servidor, que consta de cuatro partes separadas por punto y coma (;). La primera parte es la URL (o vínculo) para el extremo del servicio, la segunda es el nombre del servicio (de forma opcional, un nombre de carpeta precede al nombre de servicio), la tercera es el nombre de usuario del servidor opcional y la última es la contraseña del servidor opcional. Proporcione el nombre de usuario y la contraseña si no tiene permiso para acceder a la herramienta web.

Una herramienta web se puede ejecutar de forma sincrónica o asíncrona. Como scripter de Python, debe entender cómo se ejecuta el servicio para utilizarlo. La propiedad IsSynchronous se puede utilizar para determinar si el 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 que haya terminado de ejecutarse el servicio, puede acceder al resultado.

El siguiente código de 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://machine.domain.com/webadaptor/services;Elevation/viewshedAlias;serverusername;serverpassword")

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 tanto enviar una solicitud como enviar funciones, lo que facilita la lectura y el análisis de los mensajes JSON.

El siguiente ejemplo demuestra cómo puede conectarse al servicio, enviar una solicitud y manejar una respuesta.

Enviar la solicitud

Por ejemplo, hay un servicio de geoprocesamiento para crear cuencas visuales accesible desde https://machine.domain.com/webadaptor/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á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.

https://machine.domain.com/webadaptor/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.

# 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 = 'https://machine.domain.com/webadaptor/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. 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:

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 en ArcGIS.

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://machine.domain.com/webadaptor/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")

Temas relacionados


En este tema
  1. Uso de ArcPy
  2. Usar REST