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 un script 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 ArcPy y utilizarán los servicios de geoprocesamiento a través de él.

Nota:

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

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.


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

La ruta utilizada para importar la herramienta es la URL del servicio de geoprocesamiento. 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 URL (o vínculo) para el extremo del servicio y la segunda es el nombre del servicio (de forma opcional, un nombre de carpeta precede al nombre de servicio).

Un servicio de geoprocesamiento 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 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 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 que se pueden utilizar para realizar una solicitud y analizar un resultado; el ejemplo anterior es solo un método. 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 = "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")

En este tema
  1. Usar ArcPy
  2. Usar REST