Utilizar servicios de geoprocesamiento en scripts de Python

Puede escribir un script de Python para ejecutar y usar 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 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. 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.

Usar ArcPy

Puede acceder a un servicio de geoprocesamiento desde la ventana Python en ArcGIS Pro, una herramienta de scripts o un script independiente. La URL de servicio se utiliza para conectar y utilizar un servicio de geoprocesamiento.

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.

Un servicio de geoprocesamiento 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 un servicio de geoprocesamiento es escribir un script que realice llamadas REST con 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 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. El JSON devuelto desde un servicio de geoprocesamiento se puede colocar en un diccionario con json.loads(), tal y como se muestra en el ejemplo anterior. Dependiendo de la salida del servicio de geoprocesamiento, 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 un servicio de geoprocesamiento asíncrono (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")

En este tema
  1. Usar ArcPy
  2. Usar REST