Использование скриптов Python

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

Примечание:

В примерах ниже сервис геообработки должен быть запущен на интегрированном ArcGIS Server. Вам не нужно использовать в Python связанный элемент веб-инструмента с портала.

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

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

Пример: Подключитесь к сервису с помощью ImportToolbox с SOAP URL, сервиса в папке, используя имя пользователя и пароль.


arcpy.ImportToolbox("https://organization.example.com/<context>/services;GPFolder/BufferService;serverusername;serverpassword")

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

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

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

import arcpy
import time

arcpy.ImportToolbox("https://organization.example.com/<context>/services;Elevation/viewshedAlias;serverusername;serverpassword")

result = arcpy.viewshedAlias.Viewshed(r'c:\data.gdb\inputPoint', "10000 Kilometers")

while result.status < 4:
	   print(result.status)
	   time.sleep(0.2)
print("Tool finished")

print(result.getMessages())
arcpy.management.CopyFeatures(result, r'c:\results.gdb\result')

Дополнительные сведения об инструментах в Python

Использование точки доступа REST

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

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

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

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

К примеру, сервис геообработки для создания областей видимости доступен по ссылке https://organization.example.com/<context>/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-адрес, с помощью которого был создан запрос.

https://organization.example.com/<context>/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 приведет к выполнению приведенного выше запроса способом, аналогичным использованию каталога сервиса или копированию ссылки в адресную строку веб-браузера.


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://organization.example.com/<context>/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 имеет смысл для вашего рабочего процесса, так как фактические объекты не будут получены в формате, поддерживающем геометрию внутри ArcPy.

Сервис, который выполняется асинхронно, нуждается в периодическом запросе статуса задачи, чтобы узнать, завершена ли она (аналогично вышеприведенному примеру с использованием 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 = "https://organization.example.com/<context>/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")

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