Использование веб-инструментов в скриптах Python

Существует несколько способов написания скрипта Python, чтобы он выполнял и использовал веб-инструмент. Основной способ запуска скрипта – использовать ArcPy. ArcPy имеет встроенные методы для подключения, выполнения и обработки результатов сервиса. Как альтернатива, вы можете найти сервис в директории сервисов ArcGIS Server и использовать встроенные модули Python для вызовов REST с применением структуры JSON в целях передачи результатов. Для использования этих возможностей вам потребуется создать клиент "с нуля" с кодом Python. Большинство скриптов подключаются и используют сервисы геообработки через ArcPy.

Примечание:

Эти примеры работают непосредственно с сервисом ArcGIS Server. Вам не требуется получать веб-инструмент из портала.

Использование ArcPy

Доступ к веб-инструменту можно получить через окно Python в ArcGIS Pro, через инструмент-скрипт или автономный скрипт. Для подключения и использования веб-инструмента применяется URL-адрес сервиса.

Подключитесь к сервису при помощи ImportToolbox.


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

Путём для импорта инструмента является URL веб-инструмента.ImportToolbox кроме двух параметров: URL к сервису и дополнительный псевдоним для набора инструментов. Параметр URL-адреса разделяется на две части с использованием точки с запятой (;). Первая часть – это URL-адрес (или ссылка) конечной точки, а вторая – имя сервиса (дополнительно; имя папки предшествует имени сервиса).

Веб-инструмент может выполняться синхронно или асинхронно. Создатель сценариев Python должен понимать, как выполняется сервис, чтобы эффективно его использовать. Свойство IsSynchronous можно задействовать для определения типа выполнения сервиса. Если сервис выполняется синхронно, результат возвращается автоматически, но, до завершения работы инструмента нельзя предпринимать никаких действий. При использовании асинхронных сервисов, следует периодически опрашивать текущий статус выполнения. После выполнения сервиса можно получить доступ к результатам.

В следующем коде Python показано, как подключиться к асинхронному сервису геообработки и, применяя функции ArcPy, получить результаты и обработать их. При настройке переменной результата во время выполнения задачи можно настроить цикл while для проверки статуса. Задача завершается после возвращения кода состояния 4 (успешно) или выше.

Используйте асинхронный сервис для создания буфера и локального сохранения результатов.

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

Дополнительные сведения об объекте Result и кодах состояния, а также создании выходных растровых и картографических изображений доступны в разделе справки Использование инструментов в Python.

Использование REST

Альтернативным (но менее распространенным) способом использования веб-инструмента является написание скрипта, который выполняет вызовы REST, с использованием JSON в качестве формата обмена данных. При использовании этого метода необходимо написать код как для отправки запроса, так и для обработки ответа.

Отправка и получение сообщений REST требует большего участия разработчика, так как следует самостоятельно обрабатывать все аспекты синтаксиса для входных и выходных объектов. При отправке и получении сообщений REST они возвращаются в согласованном порядке. Запрос может быть послан с помощью метода HTTP GET или HTTP POST, а ответ вернется структурированным как JSON. Ключевые библиотеки Python поддерживают и отправку запроса, и функции, которые упрощают чтение и обработку сообщений JSON.

В приведенном ниже примере используется сервис на приведенных в качестве примера серверах Esri и демонстрируется, как следует подключаться к сервису, отправлять запрос и обрабатывать ответ.

Отправка запроса

К примеру, SampleServer6 содержит сервис геообработки для создания областей видимости. Доступ к нему осуществляется через http://sampleserver6.arcgisonline.com/ArcGIS/rest/services/Elevation. Этот сервис берет в качестве входных данных точку и расстояние, а возвращает набор объектов. Следующие входные данные позволят лучше понять сервис:

Имя параметраВходное значение

Входная точка наблюдения (GPFeatureRecordSetLayer)

{"geometryType" : "esriGeometryPoint", "spatialReference" : {"wkid" : 54003}, 'features':[{'geometry':{'x': -13308192.1956127,
'y':  4221903.58555983}}]}

Расстояние области видимости (GPLinearUnit)

{ 'distance' : 8.5, 'units' : 'esriMiles' }

Формат (формат выходных данных)

JSON

Этот запрос возвращает из сервиса JSON видимые местоположения. В адресной строке веб-браузера можно использовать полный URL-адрес, с помощью которого был создан запрос.

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

URL-адрес может быть предоставлен с помощью модуля Python urllib или urllib2. Следующий код Python приведет к выполнению приведенного выше запроса способом, аналогичным использованию каталога сервиса или копированию ссылки в адресную строку веб-браузера.


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

Объект Result возвращается в виде строки. Существует ряд различных методов, которые можно использовать для выполнения запроса и обработки результата; приведенный выше пример — это лишь один из методов. JSON, возвращаемый от веб-инструмента, может быть размещен в словарь с помощью json.loads(), как показано в предыдущем примере. В зависимости от выходных данных веб-инструмента, это может быть наилучшим способом. Или вам может понадобиться рассмотреть другие варианты обработки выходных данных при их использовании в Python с применением REST.

Примечание:

При работе с результирующими объектами убедитесь, что использование фактических пар x, y имеет смысл для вашего рабочего процесса, так как фактические объекты не будут получены в формате, поддерживающем геометрию внутри ArcGIS.

Сервис, который выполняется асинхронно, нуждается в периодическом запросе статуса задачи, чтобы узнать, завершена ли она (аналогично вышеприведенному примеру с использованием ArcPy). Код Python может искать фразу esriJobSucceeded или esriJobFailed в сообщении статуса jobStatus, которое возвращается при проверке статуса задания. В приведенном ниже примере кода демонстрируется один из способов работы с асинхронным веб-инструментом (с использованием 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")

Связанные разделы