Создание инструмента-скрипта Python с помощью arcpy.nax

Доступно с лицензией Network Analyst.

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

Примечание:

Несмотря на то, что в этом руководстве вы узнаете, как создать инструмент-скрипт в наборе .atbx, вы также создадите пользовательский инструмент геообработки с помощью Python и модуля arcpy.nax, используя набор инструментов Python (.pyt). Вы узнаете, в чем разница между инструментом-скриптом и набором инструментов Python (.pyt). Большинство из уроков в этом руководстве применимы к обоим типам инструментов.

Инструмент-скрипт, который вы создадите в этом руководстве, будет запускать анализ Областей обслуживания и записывать получившиейся полигоны областей обслуживания в класс объектов.

Примечание:

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

Инструмент будет включать следующие параметры, которые может настроить пользователь инструмента:

  • Входные пункты обслуживания—точки, вокруг которых будут вычислены полигоны Областей обслуживания
  • Выходные полигоны — выходной класс объектов, который будет создан в ходе работы инструмента
  • Сеть — набор сетевых данных или сервис сетевого анализа, который используется для вычисления Областей обслуживания
  • Режим передвижениярежим передвижения, который используется в этом анализе
  • Предельные значения — ограничения времени передвижения или расстояния для Области обслуживания
  • Единицы измерения предельных значений — единицы измерения времени или расстояния, в которых интерпретируется значение параметра Предельные значения
  • Время дня — дата и время суток, которые используются в ходе анализа
Показывает диалоговое окно для создаваемого в этом руководстве инструмента-скрипта, которое заполнено допустимыми значениями.

Объединение тестовых данных

Целью этого руководства является создание инструмента-скрипта, который может использовать любые входные данные. Никаких специальных данных не потребуется, но для тестирования инструмента-скрипта потребуется следующее:

  • Сетевой набор данных или доступ к сервису сетевого анализа
  • Точечный класс объектов с несколькими пробными точками, расположенными на той же территории, что и сеть

Если у вас нет собственных данных, вы можете скачать и использовать данные из этого руководства.

Примечание:
Это руководство может быть выполнено с использованием в качестве источника сетевых данных либо назначенного учебного сетевого набора данных, ArcGIS Online, или сервиса маршрутизации ArcGIS Enterprise, опубликованного с использованием сетевого набора данных, который охватывает географию входных данных анализа. Если вы используете ArcGIS Online, будут расходоваться кредиты. Более подробно о сервисах сетевого анализа с помощью сервиса.
Подсказка:

Предоставленные данные руководства включают в себя готовый инструмент скрипта, созданный в соответствии с шагами из этого руководства. Вы можете найти его в папке Tutorial\ScriptTool с извлеченными учебными данными.

  1. Перейдите на страницу скачивания данных.
  2. Щелкните Загрузить и сохраните файл на свой компьютер.
  3. Разархивируйте загруженный файл.

Создание инструмента

Для начала вы создадите инструмент в новом наборе и укажете для него входные и выходные параметры.

Создание набора инструментов

Создайте набор инструментов для хранения инструмента-скрипта.

  1. Откройте ArcGIS Pro и создайте новый проект с картой.
  2. На панели Каталог, находящейся по умолчанию на правой стороне приложения, щелкните правой кнопкой Папки и выберите Добавить подключение к папке Добавить подключение к папке.

    Появится диалоговое окно Добавить подключение к папке.

  3. Подключитесь к нужной папке.

    Вы создадите набор инструментов и сохраните файл инструмента-скрипта Python .py в этой папке.

  4. Щелкните правой кнопкой мыши на подключении к папке и затем Новый > Набор инструментов (.atbx).

    Будет создан файл набора инструментов с расширением .atbx. Название набора инструментов будет в режиме правки.

  5. Укажите имя набора инструментов как TutorialScriptTool.atbx.
  6. Щелкните правой кнопкой набор инструментов и щелкните Properties (Свойства).

    Появится диалоговое окно Свойства набора инструментов.

  7. В окне Подпись обновите текст на Руководство к инструменту-скрипту.
  8. В окне Псевдоним обновите псевдоним набора инструментов как TutorialScriptTool.

    Псевдоним набора инструментов используется, когда инструмент вызывается из процесса Python.

    Диалоговое окно
  9. Щелкните OK, чтобы закрыть диалоговое окно Свойства набора инструментов.

Создание инструмента-скрипта в наборе

Далее вы создадите инструмент-скрипт в наборе и обновите его базовые свойства.

  1. Щелкните правой кнопкой на созданном в предыдущем разделе наборе инструментов и щелкните Новый > Скрипт.

    Откроется диалоговое окно Новый скрипт.

  2. В списке боковых вкладок щелкните вкладку Общие, если она не выбрана.
  3. В текстовом окне Имя введите ServiceAreaTutorialScriptTool.

    Это имя используется при вызове инструмента из процесса Python. Используйте в имени только буквенно-цифровые символы. Оно не может включать пробелы и специальные символы.

  4. В текстовом окне Подпись введите Руководство инструмента-скрипта области обслуживания.

    Подпись – это отображаемое имя инструмента-скрипта, как показано на панели Геообработка, и может содержать пробелы.

    Диалоговое окно инструмента-скрипта
  5. В текстовом поле Описание введите по желанию описание инструмента-скрипта.

Задание параметров инструмента

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

Вы создадите 7 параметров, перечисленных в самом начале этого руководства.

Подробнее о настройке параметров инструмента-скрипта

  1. В списке боковых вкладок щелкните вкладку Параметры.
  2. Чтобы создать параметр Входные пункты обслуживания, выполните следующие шаги:

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

    1. Щелкните первую пустую ячейку в столбце Подпись, введите Входные пункты обслуживания и нажмите Enter.

      Будет создан параметр Входные пункты обслуживания. Ячейка в столбце Имя будет автоматически обновлена на значение Input_Facilities.

    2. Щелкните кнопку Опции Опции в ячейке Тип данных, чтобы открыть диалоговое окно Тип данных параметра.
    3. В диалоговом окне Тип данных параметра в ниспадающем меню выберите Векторный слой и щелкните OK, чтобы закрыть диалоговое окно.
      Диалоговое окно Тип данных параметра показывает выбранный тип Векторный слой.

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

    4. Щелкните ячейку в столбце Фильтр. Пролистайте вправо, чтобы найти этот столбец.
    5. Используйте ниспадающее меню, чтобы выбрать опцию Тип объекта.
      Выберите фильтр Тип объекта для параметра Входные объекты.

      Появится диалоговое окно Фильтр типа объектов.

    6. В диалоговом окне Фильтр типа объектов поставьте отметку для опции Точка и затем OK, чтобы закрыть диалоговое окно.
      Диалоговое окно Фильтр типа объекта с отмеченной опцией Точка

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

  3. Чтобы создать параметр Выходные полигоны, выполните следующие шаги:

    Параметр Выходные полигоны позволяет выбрать локацию, в которую инструмент сохранит созданный в ходе запуска полигональный класс объектов Областей обслуживания.

    1. Щелкните на первой пустой ячейке под столбцом Подпись, введите Выходные полигоны и нажмите Enter.

      Создается параметр Выходные полигоны. Ячейка в столбце Имя автоматически обновится на Output_Polygons.

    2. Как и в случае с определением типа данных для параметра Входные пункты обслуживания, щелкните ячейку Тип данных, чтобы открыть диалоговое окно Тип данных параметра. Сейчас вам нужно задать тип данных как Класс объектов.

      Выходной параметр типа Класс объектов позволяет выбрать путь к каталогу для нового класса объектов.

    3. Щелкните ячейку в столбце Направление и в ниспадающем меню выберите опцию Выходные данные.

      Поскольку этот параметр настроен как выходной, пользователь может выбрать путь к выходному файлу, а также имя для класса объектов, который еще не существует.

  4. Чтобы создать параметр Сеть, выполните следующие шаги:

    Параметр Сеть позволит выбрать набор сетевых данных или сервис сетевого анализа для вычисления Областей обслуживания.

    1. Щелкните первую пустую ячейку в столбце Подпись, введите Сеть и нажмите Enter.

      Будет создан параметр Сеть. Ячейка в столбце Имя автоматически обновится на Сеть.

    2. В столбце Тип данных задайте тип данных как Источник сетевых данных.

      Тип параметра Источник сетевых данных позволяет выбрать слой набора сетевых данных, путь в каталоге с набором сетевых данных, либо URL к сервису сетевого анализа. Для параметра типа Слой набора сетевых данных пользователь может выбрать слой набора сетевых данных или путь в каталоге к набору сетевых данных, опция URL к сервису будет недоступна. Тип параметра Набор сетевых данных позволяет выбирать только путь в каталоге к набору сетевых данных и обычно используется как выходной параметр, а не входной.

  5. Чтобы создать параметр Режим передвижения, выполните следующие шаги:

    Параметр Режим передвижения позволит выбрать режим передвижения, который используется в этом анализе. Вы настроите этот параметр с зависимостью, чтобы список для выбора автоматически обновлялся и отражался режимы передвижения, доступные с выбранным значением параметра Сеть.

    1. Щелкните первую пустую ячейку под столбцом Подпись, введите Режим передвижения и нажмите Enter.

      Будет создан параметр Режим передвижения. Ячейка в столбце Имя автоматически обновится на Режим_Передвижения.

    2. В столбце Тип данных задайте тип данных как Режим передвижения по сети.
    3. Щелкните ячейку в столбце Зависимость. Пролистайте вправо, чтобы найти этот столбец.
    4. В ниспадающем меню в ячейке столбца Зависимость выберите опцию Сеть.
      Выберите параметр Сеть в ниспадающем меню в столбце Зависимость для параметра Режим передвижения.

      Параметр Режим передвижения теперь связан с параметром Сеть. Диалоговое окно инструмента автоматически обновит список выбора в параметре Режим передвижения в соответствии со значением, заданным в параметре Сеть.

  6. Чтобы создать параметр Предельные значения, выполните следующие шаги:

    Параметр Предельные значения позволит выбирать одно или несколько числовых значений, определяющих ограничения по времени в пути или по расстоянию для областей обслуживания. Полигоны Областей обслуживания будут показывать области, которые достижимы от входных пунктов обслуживания в пределах заданных ограничений. Если введено несколько значений, то для каждого пункта обслуживания по каждому предельному значению будет создан отдельный полигон Области обслуживания. Например, выходные данных могут включать полигоны, представляющие 10 и 15-минутные области обслуживания вокруг каждого пункта.

    1. Щелкните первую пустую ячейку под столбцом Подпись, введите Предельные значения и нажмите Enter.

      Будет создан параметр Предельные значения. Ячейка в столбце Имя автоматически обновится на Предельные значения.

    2. Щелкните кнопку Опции Опции в ячейке Тип данных, чтобы открыть диалоговое окно Тип данных параметра.
    3. В диалоговом окне Тип данных параметра выберите из ниспадающего меню Double.
    4. В диалоговом окне Тип данных параметра поставьте отметку напротив опции Несколько значений.
      Диалоговое окно Тип данных параметра, где выбран тип Double и отмечена опция Несколько значений.

      Опция Несколько значений позволяет указывать больше одного значения для параметра.

    5. Щелкните OK, чтобы закрыть диалоговое окно Тип данных параметра.

    Предельные значения Области обслуживания должны быть больше нуля. Полигоны с 0 минут или отрицательным временем создаваться не будут. Можно настроить числовой параметр с фильтром по диапазону, выбрав опцию Диапазон в столбце Фильтр. Если пользователь выбирает число за пределами этого диапазона, появится сообщение об ошибке. Однако фильтры диапазона поддерживают только входящие в них числовые диапазоны, а вы, допустим, хотите исключить нижнюю границу 0, но при этом разрешить десятичные значения, такие как 0,5. Следовательно, вместо использования предоставленного фильтра диапазона вы будете использовать проверку инструмента для создания собственного фильтра диапазона с помощью кода Python. Это будет описано в данном руководстве позднее.

  7. Чтобы создать параметр Единицы измерения предельных значений, выполните следующие шаги:

    Параметр Единицы измерения предельных значений позволяет указывать единицы измерения, в которых будет интерпретироваться значение параметра Предельные значения.

    1. Щелкните первую пустую ячейку под столбцом Подпись, введите Единицы измерения и нажмите Enter.

      Будет создан параметр Единицы измерения предельных значений. Ячейка в столбце Имя автоматически обновится на Единицы_измерения_предельных_значений.

    2. В столбце Тип данных убедитесь, что тип данных задан как String, обновите его при необходимости.

    Чтобы настроить список выбора для параметра, вы можете выбрать опцию Список значений в столбце Фильтр и ввести список значений, который хотите показать пользователю. Однако для параметра Единицы измерения предельных значенийвы хотите, чтобы список выбора был динамическим в зависимости от того, имеет ли выбранное пользователем значение параметра Режим передвижения единицы времени или расстояния. В следующем разделе вы будете использовать проверку инструмента для построения списка динамического выбора с помощью кода Python.

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

    Параметр Время дня позволяет задать дату и время дня для выполнения анализа. В эту дату и время транспортное средство или пешеход будет выезжать из пункта обслуживания. Поскольку время дня не всегда используется, вы настроите этот параметр как дополнительный. Пользователь может настроить этот параметр, если необходимо, либо оставить его пустым.

    1. Щелкните первую пустую ячейку под столбцом Подпись, введите Время дня и нажмите Enter.

      Будет создан параметр Время дня. Ячейка в столбце Имя автоматически обновится на Время_дня.

    2. В столбце Тип данных задайте тип данных как Дата.
    3. Щелкните ячейку в столбце Тип и в ниспадающем меню выберите опцию Дополнительный.

      Поскольку этот параметр настроен как дополнительный, пользователь может оставить его пустым, это не приведет к ошибке.

  9. Отметьте конфигурацию параметра. Окно должно выглядеть примерно так же, как и на следующей картинке:
    Полная конфигурация параметров для инструмента-скрипта
  10. Щелкните OK в диалоговом окне Новый скрипт, чтобы подтвердить внесенные изменения и закройте диалоговое окно.

Проверьте параметры инструмента

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

  1. На панели Каталог найдите новый инструмент-скрипт Service Area Tutorial Script Tool в наборе инструментов.
    Набор инструментов и инструмент-скрипт на панели Каталог
  2. Дважды щелкните инструмент, чтобы открыть его.

    Service Area Tutorial Script Tool откроется на панели Геообработка. Будут видны 7 параметров, которые вы создали в предыдущем разделе.

    Диалоговое окно инструмента-скрипта на панели Геообработка, где показаны все параметры.
  3. Изучите каждый параметр и убедитесь, что он настроен соответствующим образом.
    1. Проверьте параметр Входные пункты обслуживания.

      В этом параметре у вас должна быть возможность выбирать только точечные слои и классы объектов. Полигональные и линейные классы объектов не появятся в списке для выбора, если же вы введете их вручную, то появится сообщение об ошибке, где написано, что тип геометрии некорректен.

      Подсказка:
      Вы не будете видеть список для выбора, если на вашей карте нет подходящих слоев. Добавьте на свою карту несколько слоев, чтобы проверить работоспособность параметра.

    2. Проверьте параметр Выходные полигоны.

      У вас должна быть возможность выбора выходной локации. Если вы выбираете существующий класс объектов, то параметр должен показать предупреждение о том, что выходной набор данных уже есть.

    3. Проверьте параметры Сеть и Режим передвижения.

      Параметр Режим передвижения сначала должен быть пустым, без списка для выбора. Параметр Сеть должен позволять выбирать слой набора сетевых данных, путь в каталоге к набору сетевых данных, либо URL к сервису сетевого анализа.

    4. Выберите значение для параметра Сеть.

      Список для выбора в параметре Режим передвижения автоматически обновится, в него войдет список доступных режимов передвижения, связанных со значением Сеть.

    5. Изучите параметр Предельные значения.

      Вы можете ввести больше одного числового значения.

      В настоящий момент вы можете указать и отрицательные числа, либо 0, параметр при этом не будет выдавать ошибку. Позднее вы будете использовать проверку инструмента, чтобы скорректировать это поведение.

    6. Изучите параметр Единицы измерения предельных значений.

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

    7. Изучите параметр Время дня.

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

Написание скрипта Python

В этом разделе вы напишете скрипт Python, который будет запускать ваш инструмент. Инструмент-скрипт будет делать следующее:

  • Получать входные параметры.
  • Проверять наличие лицензии Расширение ArcGIS Network Analyst, если требуется.
  • Запускать анализ Области обслуживания.
  • Настраивать параметры анализа Области обслуживания.
  • Загружать входные пункты обслуживания.
  • Выполнять расчет анализа Областей обслуживания и обрабатывать возникшие ошибки.
  • Записывать полученные полигоны Областей обслуживания в класс объектов.

  1. Создайте файл с названием ServiceAreaTutorialScriptTool.py в той же папке, где вы уже ранее создали набор инструментов, и откройте его для редактирования в интегрированной среде разработки (IDE), либо в текстовом редакторе (на ваш выбор).

    В этом упражнении вы можете использовать любую Python IDE или текстовый редактор.

  2. Прочитайте подразделы ниже, чтобы понять компоненты кода, который вы будете использовать для инструмента-скрипта.
  3. Полный код приведен в нижней части этого раздела. Скопируйте и вставьте этот код в файл ServiceAreaTutorialScriptTool.py и сохраните его.

    Внимание:
    Проверьте, что отступы в коде корректны после того, как вы вставили его в файл ServiceAreaTutorialScriptTool.py.

Получение входных параметров

Код инструмента-скрипта должен получать входные данные пользователя из параметров инструмента с помощью функций ArcPy GetParameter или GetParameterAsText. Функция GetParameter возвращает значение параметра в указанный тип данных параметра, а функция GetParameterAsText всегда возвращает значение параметра как строку.

В этом фрагменте кода скрипт получает параметры инструмента и назначает их переменным. Функция GetParameter используется, когда вы хотите получить тип данных входного параметра. Функция GetParameterAsText используется при извлечении входных пунктов обслуживания и источника сетевых данных, даже если эти входные данные могут быть слоями, поскольку строковые имена слоев могут использоваться в качестве допустимых входных данных для инструментов геообработки и функций ArcPy. Значения индекса, которые здесь используются с GetParameter и GetParameterAsText, соответствуют порядку параметров, который вы определили ранее.

input_facilities = arcpy.GetParameterAsText(0)
output_polygons = arcpy.GetParameterAsText(1)
network = arcpy.GetParameterAsText(2)
travel_mode = arcpy.GetParameter(3)
cutoffs = arcpy.GetParameter(4)
cutoff_units = arcpy.GetParameterAsText(5)
time_of_day = arcpy.GetParameter(6)

Проверка лицензии на Расширение ArcGIS Network Analyst

Лицензия на Расширение ArcGIS Network Analyst необходима, если пользователь инструмента выбирает набор сетевых данных в параметре Сеть. Если же пользователь выбирает использовать сервис сетевого анализа, указав URL портала, лицензия на Расширение ArcGIS Network Analyst не требуется.

В этом фрагменте кода скрипт пытается получить лицензию на дополнительный модуль, если входная сеть не начинается с http, что предположительно является сервисом сетевого анализа. Если дополнительный модуль недоступен, появится ошибка. Работа с ошибками будет рассматриваться в этом руководстве позднее.

# Check out the Network Analyst extension license if the input network
# is a local network dataset and not a service.
if not network.startswith("http"):
    if arcpy.CheckExtension("network") == "Available":
        arcpy.CheckOutExtension("network")
    else:
        # Throw an error if the license cannot be checked out.
        arcpy.AddError("The Network Analyst license is unavailable.")
        raise CustomError

Запуск анализа Областей обслуживания

Первым шагом в рабочем процессе сетевого анализа, который использует arcpy.nax, будет создание экземпляра объекта анализа механизма расчета с использованием назначенного источника сетевых данных.

Подробнее о шагах в рабочем процессе сетевого анализа с использованием arcpy.nax.

В этом фрагменте кода инициализирован объект анализа Области обслуживания.

# Instantiate the ServiceArea solver object
sa = arcpy.nax.ServiceArea(network)

Настройка параметров анализа Области обслуживания.

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

Подробнее о настройках анализа Областей обслуживания

В этом фрагменте кода некоторые настройки анализа жестко закодированы. Режим передвижения, время суток и предельные значения импеданса по умолчанию устанавливаются с использованием значений, полученных из параметров инструмента.

# Hard-code some non-default Service Area settings that we don't want
# the user to change
sa.geometryAtCutoff = arcpy.nax.ServiceAreaPolygonCutoffGeometry.Disks
sa.polygonBufferDistance = 150
sa.polygonBufferDistanceUnits = arcpy.nax.DistanceUnits.Feet

# Set analysis properties chosen by the user and passed in via tool
# parameters
sa.travelMode = travel_mode
sa.timeOfDay = time_of_day
sa.defaultImpedanceCutoffs = cutoffs

Вам также потребуется задать единицы измерения предельных значений, но это потребует немного дополнительной обработки. Этот параметр инструмента будет настроен как строка, поэтому вам нужно преобразовать имя единицы на основе строки в соответствующее значение перечисления TimeUnits или DistanceUnits.

В этом фрагменте кода устанавливаются единицы времени или единицы расстояния, в зависимости от значения, переданного из параметра инструмента, с помощью двух функций для преобразования строкового значения в соответствующее значение перечисления. В этом демонстрационном примере вы будете поддерживать только ограниченный список допустимых единиц измерения времени и расстояния. Этот параметр инструмента будет рассматриваться в данном руководстве позднее.

# Do special handling of cutoff units to convert them to the correct
# arcpy.nax enum
if cutoff_units in ["Hours", "Minutes"]:
    sa.timeUnits = convert_time_units_to_nax(cutoff_units)
elif cutoff_units in ["Kilometers", "Meters", "Miles", "Yards", "Feet"]:
    sa.distanceUnits = convert_distance_units_to_nax(cutoff_units)

В этом фрагменте кода определены две функции для преобразования имен единиц на основе строк в правильное значение перечисления. Не все возможные значения перечислений TimeUnits и DistanceUnits включены, потому что в этом примере вы ограничите выбор единиц, представленных пользователям. Функции будут вызывать ошибку, если передается недопустимая единица измерения.

def convert_time_units_to_nax(time_units_str):
    """Convert string-based time units to the correct arcpy.nax enum."""
    if time_units_str == "Hours":
        return arcpy.nax.TimeUnits.Hours
    if time_units_str == "Minutes":
        return arcpy.nax.TimeUnits.Minutes
    arcpy.AddError(f"Invalid time units: {time_units_str}")
    raise CustomError


def convert_distance_units_to_nax(dist_units_str):
    """Convert string-based distance units to the correct arcpy.nax enum."""
    if dist_units_str == "Kilometers":
        return arcpy.nax.DistanceUnits.Kilometers
    if dist_units_str == "Meters":
        return arcpy.nax.DistanceUnits.Meters
    if dist_units_str == "Miles":
        return arcpy.nax.DistanceUnits.Miles
    if dist_units_str == "Yards":
        return arcpy.nax.DistanceUnits.Yards
    if dist_units_str == "Feet":
        return arcpy.nax.DistanceUnits.Feet
    arcpy.AddError(f"Invalid distance units: {dist_units_str}")
    raise CustomError

Загрузка входных пунктов обслуживания

Вы будете использовать метод load для добавления пунктов обслуживания в анализ области обслуживания.

Подробнее о других способах настройки входных параметров анализа

В этом фрагменте кода входные пункты обслуживания добавляются в анализ Областей обслуживания с помощью метода load. Значение перечисления ServiceAreaInputDataType.Facilities используется в качестве параметра метода load, чтобы указать, что входные данные должны быть добавлены в качестве объектов.

# Load the input facilities
sa.load(arcpy.nax.ServiceAreaInputDataType.Facilities, input_facilities)

Выполнение расчета анализа Областей обслуживания и обработка возникших ошибок

Теперь, когда настроены параметры Области обслуживания и загружены входные данные, вы готовы к запуску анализа и получению результата. Выполнение анализа с использованием метода расчета создает экземпляр объекта ServiceAreaResult, который включает свойства и методы для работы с результатами анализа.

В этом фрагменте кода анализ Области обслуживания выполняется с использованием метода solve. Переменную result можно использовать для работы с результатами анализа.

# Solve the analysis
result = sa.solve()

Иногда анализ может завершиться ошибкой или может быть выполнен успешно, но пользователю будут возвращены предупреждающие сообщения о возможных проблемах. В этом инструменте вы настроите механизм расчета таким образом, чтобы он возвращал ошибки и предупреждения пользователю. Если расчет не будет выполнен, вы хотите остановить работу инструмента.

В этом фрагменте кода методServiceAreaResult объекта solverMessages используется для получения предупреждений с использованием значения перечисления MessageSeverity.Warning. Каждое полученное сообщение-предупреждение добавляется в предупреждающие сообщения от инструмента с помощью функции AddWarning.

# Print warning messages if there are any
for warning in result.solverMessages(arcpy.nax.MessageSeverity.Warning):
    arcpy.AddWarning(warning[1])

В этом фрагменте кода вы проверяете, успешно ли выполнен анализ Областей обслуживания с помощью свойства ServiceAreaResult объекта solveSucceeded. Если нет, то используется метод solverMessages для получения сообщений об ошибках, а функция AddError добавляет их в ошибки инструмента. Кроме того, ошибка останавливает дальнейшую работу инструмента. Работа с ошибками будет рассматриваться немного позднее.

# Handle failed solves
if not result.solveSucceeded:
    arcpy.AddError("The Service Area solve failed.")
    # Print error messages and stop the tool from running further
    for error in result.solverMessages(arcpy.nax.MessageSeverity.Error):
        arcpy.AddError(error[1])
    # Stop tool run by raising an error
    raise CustomError

Запись полученных полигонов Областей обслуживания в класс объектов

И, наконец, вы записываете результаты анализа Областей обслуживания в назначенный пользователем класс объектов с помощью метода export. Также вы выполняете подсчет числа полигонов в полученном результате с помощью счетчика method и записываете эту информацию в виде сообщения.

Подробнее о других способах доступа и работы с выходными данными анализа

В этом фрагменте кода число полученных полигонов записывается как сообщение с помощью функции AddMessage, а полигоны Областей обслуживания экспортируются в класс объектов. Значение перечисления ServiceAreaOutputDataType.Polygons используется для работы с выходными полигонами вместо любого из других типов результатов анализа.

# Add a message with the total number of polygons that were generated
# in the analysis
num_polygons = result.count(
    arcpy.nax.ServiceAreaOutputDataType.Polygons)
arcpy.AddMessage(f"Number of polygons generated: {num_polygons}.")

# Export the Service Area polygons to the output feature class
result.export(
    arcpy.nax.ServiceAreaOutputDataType.Polygons, output_polygons)

Работа с ошибками

При обнаружении известной ошибки вы хотите, чтобы инструмент прекратил работу и выдал полезное сообщение об ошибке. Вы сделаете это, вызвав пользовательское исключение и заключив код запуска инструмента в блок try/except.

В этом фрагменте кода определяется пользовательское исключение. Он ничего не делает, только служит для остановки работы инструмента при обнаружении известной проблемы.

class CustomError(Exception):
    pass

Код запуска инструмента заключен в блок try/except. Если выявлена CustomError, код ничего не делает, потому что сообщение об ошибке уже добавлено к ошибкам инструмента. Если возникает неизвестная ошибка, код извлекает traceback и добавляет его в качестве ошибки инструмента для облегчения отладки.

try:

    [...]

except CustomError:
    # We caught a known error and already added the message. Do nothing.
    pass

except Exception:
    # An unknown error occurred. Add the traceback as an error message.
    arcpy.AddError(
        "An unknown error occurred when generating Service Areas.")
    import traceback
    arcpy.AddError(traceback.format_exc())

Сложите все это вместе

Следующий фрагмент кода содержит полный скрипт Python, включающий все описанные выше компоненты. Вы можете скопировать и вставить этот код в файл ServiceAreaTutorialScriptTool.py.

import arcpy


class CustomError(Exception):
    pass


def convert_time_units_to_nax(time_units_str):
    """Convert string-based time units to the correct arcpy.nax enum."""
    if time_units_str == "Hours":
        return arcpy.nax.TimeUnits.Hours
    if time_units_str == "Minutes":
        return arcpy.nax.TimeUnits.Minutes
    arcpy.AddError(f"Invalid time units: {time_units_str}")
    raise CustomError


def convert_distance_units_to_nax(dist_units_str):
    """Convert string-based distance units to the correct arcpy.nax enum."""
    if dist_units_str == "Kilometers":
        return arcpy.nax.DistanceUnits.Kilometers
    if dist_units_str == "Meters":
        return arcpy.nax.DistanceUnits.Meters
    if dist_units_str == "Miles":
        return arcpy.nax.DistanceUnits.Miles
    if dist_units_str == "Yards":
        return arcpy.nax.DistanceUnits.Yards
    if dist_units_str == "Feet":
        return arcpy.nax.DistanceUnits.Feet
    arcpy.AddError(f"Invalid distance units: {dist_units_str}")
    raise CustomError


def generate_service_areas():
    """Generate Service Area polygons."""
    try:
        input_facilities = arcpy.GetParameterAsText(0)
        output_polygons = arcpy.GetParameterAsText(1)
        network = arcpy.GetParameterAsText(2)
        travel_mode = arcpy.GetParameter(3)
        cutoffs = arcpy.GetParameter(4)
        cutoff_units = arcpy.GetParameterAsText(5)
        time_of_day = arcpy.GetParameter(6)

        # Check out the Network Analyst extension license if the input network
        # is a local network dataset and not a service.
        if not network.startswith("http"):
            if arcpy.CheckExtension("network") == "Available":
                arcpy.CheckOutExtension("network")
            else:
                # Throw an error if the license cannot be checked out.
                arcpy.AddError("The Network Analyst license is unavailable.")
                raise CustomError

        # Instantiate the ServiceArea solver object
        sa = arcpy.nax.ServiceArea(network)

        # Hard-code some non-default Service Area settings that we don't want
        # the user to change
        sa.geometryAtCutoff = arcpy.nax.ServiceAreaPolygonCutoffGeometry.Disks
        sa.polygonBufferDistance = 150
        sa.polygonBufferDistanceUnits = arcpy.nax.DistanceUnits.Feet

        # Set analysis properties chosen by the user and passed in via tool
        # parameters
        sa.travelMode = travel_mode
        sa.timeOfDay = time_of_day
        sa.defaultImpedanceCutoffs = cutoffs
        # Do special handling of cutoff units to convert them to the correct
        # arcpy.nax enum
        if cutoff_units in ["Hours", "Minutes"]:
            sa.timeUnits = convert_time_units_to_nax(cutoff_units)
        elif cutoff_units in ["Kilometers", "Meters", "Miles", "Yards", "Feet"]:
            sa.distanceUnits = convert_distance_units_to_nax(cutoff_units)

        # Load the input facilities
        sa.load(arcpy.nax.ServiceAreaInputDataType.Facilities, input_facilities)

        # Solve the analysis
        result = sa.solve()

        # Print warning messages if there are any
        for warning in result.solverMessages(arcpy.nax.MessageSeverity.Warning):
            arcpy.AddWarning(warning[1])

        # Handle failed solves
        if not result.solveSucceeded:
            arcpy.AddError("The Service Area solve failed.")
            # Print error messages and stop the tool from running further
            for error in result.solverMessages(arcpy.nax.MessageSeverity.Error):
                arcpy.AddError(error[1])
            # Stop tool run by raising an error
            raise CustomError

        # Add a message with the total number of polygons that were generated
        # in the analysis
        num_polygons = result.count(
            arcpy.nax.ServiceAreaOutputDataType.Polygons)
        arcpy.AddMessage(f"Number of polygons generated: {num_polygons}.")

        # Export the Service Area polygons to the output feature class
        result.export(
            arcpy.nax.ServiceAreaOutputDataType.Polygons, output_polygons)

    except CustomError:
        # We caught a known error and already added the message. Do nothing.
        pass

    except Exception:
        # An unknown error occurred. Add the traceback as an error message.
        arcpy.AddError(
            "An unknown error occurred when generating Service Areas.")
        import traceback
        arcpy.AddError(traceback.format_exc())


if __name__ == "__main__":
    generate_service_areas()

Настройка инструмента-скрипта для запуска файла скрипта Python

Ранее вы создали инструмент-скрипт и задали его параметры. Итак, вы написали скрипт Python для выполнения этого анализа. Теперь вы должны настроить инструмент для запуска этого скрипта Python. Когда вы запустите инструмент, он в свою очередь запустит код в скрипте Python, а скрипт Python получит входные данные, переданные в него из параметров инструмента, а затем выполнит сам анализ.

  1. Откройте диалоговое окно свойств инструмента-скрипта, щелкнув на нем правой кнопкой и выбрав Свойства.

    Появится диалоговое окно Свойства инструмента.

  2. В списке боковых вкладок щелкните вкладку Выполнение.
  3. Щелкните кнопку Папка Папка и перейдите к локации, где лежит файл скрипта ServiceAreaTutorialScriptTool.py.

    Подсказка:
    Если файл ServiceAreaTutorialScriptTool.py не появляется в диалоговом окне обзора, щелкните кнопку Обновить рядом с адресной строкой вверху.Кнопка для обновления диалогового окна обзора

    Код, показанный на вкладке Выполнение, обновится, там появится содержимое файла скрипта Python. Теперь инструмент настроен для запуска скрипта Python.

Настройка проверки инструмента

Проверка относится к процессу, который проверяет и обновляет значения параметров инструмента перед его запуском. Проверка может гарантировать, что значения, введенные для параметров, относятся к правильному типу или диапазону значений. Проверка также может обновлять списки выбора параметров или даже скрывать или отображать параметры в зависимости от значения других параметров.

Некоторые процессы проверки встроены в определенные типы параметров и конфигурации. Например, ранее вы настроили для параметра Входные пункты обслуживания фильтр Тип объекта, чтобы принимать на вход только точечные классы объектов. Когда пользователь выбирает входные для этого параметра, проверка проверяет правильность типа входных данных и отображает сообщение об ошибке, если это не так.

Однако иногда автору инструмента-скрипта необходимо реализовать более сложную или настраиваемую проверку. Это можно сделать с помощью класса ToolValidator. Этот специальный класс Python можно обновить с помощью пользовательского кода для обновления параметров и выполнения проверок, которые при необходимости вызывают сообщения об ошибках и предупреждения.

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

Код ToolValidator расположен отдельно от скрипта Python, который вы написали ранее, поэтому инструмент запускается, а доступ и редактирование доступны по отдельности.

Примечание:

Также вы можете создать пользовательский инструмент геообработки в наборе инструментов Python (.pyt). В этом случае и код проверки, и код запуска инструмента включаются в один и тот же скрипт Python.

Подробнее о том, что можно сделать с проверкой инструмента-скрипта

Найдите класс ToolValidator и откройте его для редактирования

Когда вы создаете инструмент-скрипт, класс ToolValidator создается автоматически. Вы можете обратиться к нему через диалоговое окно свойств инструмента-скрипта и открыть его для редактирования.

  1. Откройте диалоговое окно свойств инструмента-скрипта, щелкнув на нем правой кнопкой и выбрав Свойства.

    Появится диалоговое окно Свойства инструмента.

  2. В списке боковых вкладок щелкните вкладку Проверка.

    В нем будет виден класс ToolValidator инструмента-скрипта. Вы можете изменить код непосредственно в диалоговом окне, либо щелкните кнопку Открыть в редакторе скриптов, чтобы открыть ToolValidator в отдельном файле в IDE или текстовом редакторе.

    Подсказка:

    Вы можете выбрать, какой IDE или текстовый редактор открывает файл, с помощью настройки Редактор скриптов в Опциях геообработки.

Выдача ошибки в случае, если значение параметра Предельные значения меньше или равно 0

Метод updateMessages класса ToolValidator можно использовать для проверки значений параметра, а также для добавления сообщений об ошибках или предупреждениях. В этом разделе вы измените метод updateMessages, чтобы появилось сообщение об ошибке, если значение в параметре Предельные значения было меньше или равно 0.

  1. Найдите метод updateMessages в классе ToolValidator.

    По умолчанию метод updateMessages содержит только возвращаемое выражение. Он не содержит пользовательскую проекту.

  2. Измените метод updateMessages, чтобы использовать следующий код:

    Внимание:
    Проверьте отступы кода проверки после вставки его в класс ToolValidator.

    def updateMessages(self):
        # Customize messages for the parameters.
        # This gets called after standard validation.
    
        # Raise an error if any of the cutoffs are <= 0
        cutoffs_param = self.params[4]
        if cutoffs_param.valueAsText:
            for cutoff in cutoffs_param.values:
                if cutoff <= 0:
                    cutoffs_param.setErrorMessage("Cutoffs must be positive.")
                    break
    
        return

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

    Параметр Предельные значения извлекается с помощью переменной self.params, которая представляет собой список параметров инструмента, встроенных в класс ToolValidator. Параметр Предельные значения является пятым по счету, соответственно доступ к нему осуществляется через индекс 4 в списке. Извлеченное значение будет объектом Parameter.

    Если параметр пустой, то значение проверять не нужно. Свойство Parameter объекта valueAsText - это быстрый способ определить, является ли параметр пустым.

    Поскольку это многозначный параметр, список значений извлекается с использованием свойства values. Код выполняет итерации по текущим значениям параметра.

    Если предельное значение меньше или равно 0, то класс Parameter объекта setErrorMessage будет использоваться для возвращения ошибки. Это сообщение появится на параметре в пользовательском интерфейсе инструмента.

    Если встречается недопустимое значение, выражение break останавливает итерацию. Нет необходимости проверять оставшиеся значения после того, как будет найдено недопустимое.

    Примечание:
    Даже если вы добавите пользовательский код проверки, базовая внутренняя проверка, связанная с каждым параметром, все равно будет применяться. Например, поскольку вы определили для параметра Предельные значения тип double, внутренняя проверка автоматически выявит, является ли ввод допустимым числовым значением, и при необходимости вызовет ошибку. Любая пользовательская проверка, которую вы добавляете для своего параметра, является дополнением к внутренней проверке, автоматически предоставляемой для этого типа параметра.

Заполните параметр Единицы измерения предельных значений списком единиц измерения времени или расстояния

Режим передвижения включает в себя несколько настроек, управляющих тем, как моделируется перемещение по сети. Он определяет, какая переменная оптимизируется при поиске кратчайшего пути в сети. Как правило, это мера либо времени, либо расстояния, хотя наборы сетевых данных также можно настроить для оптимизации некоторого другого типа переменных, например энергии или денежных затрат на поездку.

Параметр Предельные значения позволяет указать числовые значения для ограничения стоимости проезда в зоне обслуживания. Параметр Единицы измерения предельных значений позволяет указывать единицы измерения, в которых будет интерпретироваться это значение.

Для вашего инструмента вы хотите предоставить пользователю список допустимых единиц; однако, если выбранный режим движения оптимизирует время, вы хотите отображать только единицы времени, а если выбранный режим движения оптимизирует расстояние, вы хотите отображать только единицы расстояния. В тех редких случаях, когда режим передвижения оптимизирует какой-либо другой тип затрат, вы не хотите показывать ни единицы времени, ни единицы расстояния.

Метод updateParameters класса ToolValidator можно использовать для обновления списков выбора параметра. В этом разделе вы измените метод updateParameters, чтобы задать список выбора Единицы измерения предельных значений с соответствующим списком единиц измерения, зависящих от значений в параметре Режим передвижения.

  1. Найдите метод updateParameters в классе ToolValidator.

    По умолчанию метод updateParameters содержит только возвращаемое выражение. Он не обновляет параметры.

  2. Измените метод updateParameters, чтобы использовать следующий код:

    Внимание:
    Проверьте отступы кода проверки после вставки его в класс ToolValidator.

    def updateParameters(self):
        # Modify parameter values and properties.
        # This gets called each time a parameter is modified, before
        # standard validation.
    
        # Set filter list of units in cutoff units parameter based on what type
        # of travel mode is selected
        travel_mode_param = self.params[3]
        cutoff_units_param = self.params[5]
        if travel_mode_param.valueAsText:
            try:
                tm_object = travel_mode_param.value
                if tm_object.impedance == tm_object.timeAttributeName:
                    # The impedance has units of time, so present time units as
                    # options
                    cutoff_units_param.filter.list = ["Hours", "Minutes"]
                elif tm_object.impedance == tm_object.distanceAttributeName:
                    # The impedance has units of distance, so present distance
                    # units as options
                    cutoff_units_param.filter.list = [
                        "Kilometers", "Meters", "Miles", "Yards", "Feet"]
                else:
                    # The impedance has units that are neither time nor
                    # distance, so present only one option, "Other". The
                    # Service Area cutoffs will be interpreted in the impedance
                    # units.
                    cutoff_units_param.filter.list = ["Other"]
            except Exception:
                pass
    
        return

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

    Параметры извлекаются с помощью переменной self.params. Параметр Режим передвижения идет под индексом 3 (четвертый параметр), а параметр Единицы измерения предельных значений под индексом 5 (шестой параметр).

    Если параметр Режим передвижения окажется пустым, то параметр Единицы измерения предельных значений обновлять не нужно. Свойство объекта Parameter valueAsText - это быстрый способ определить, является ли параметр пустым.

    Значение параметра Режим передвижения извлекается как объект TravelMode с помощью свойства Parameter объекта value.

    Самым простым способом определить, оптимизирует ли режим передвижения время, расстояние или какие-то другие единицы измерения, будет сравнить свойство TravelMode объекта impedance со свойством timeAttributeName и свойством distanceAttributeName. Свойство impedance возвращает имя сетевого атрибута, который должен быть оптимизирован. Режимы передвижения также включают атрибут времени по умолчанию (timeAttributeName) и атрибут расстояния (distanceAttributeName). Если impedance совпадает с timeAttributeName, то режим передвижения оптимизирует время, а параметр Единицы измерения предельных значений обновляется и отображает единицы измерения времени. Если impedance совпадает с distanceAttributeName, то режим передвижения оптимизирует расстояния, а параметр Единицы измерения предельных значений обновляется и отображает единицы измерения расстояния. Если impedance не совпадает ни с чем, то режим передвижения оптимизирует некоторые другие переменные, а предельные значения Области обслуживания будут интерпретироваться в этих единицах измерения. Параметр Единицы измерения предельных значений будет обновлен и станет показывать только один вариант выбора: Прочее.

    Во всех случаях список для выбора настраивается с помощью конфигурации Единиц измерения предельных значений объекта Parameter свойства filter.list.

    Блок кода заключен в блок try/except. Если при чтении режима движения возникают ошибки, код ничего не делает и не обновляет список выбора.

Проверка валидации инструмента

В этом разделе вы сохраните и протестируете код валидации.

  1. Если вы открыли класс ToolValidator в IDE или текстовом редакторе, сохраните и закройте файл.
  2. Щелкните OK в диалоговом окне Свойства инструмента, чтобы подтвердить изменения.
  3. На панели Каталог дважды щелкните инструмент, чтобы его открыть.

    Service Area Tutorial Script Tool откроется на панели Геообработка.

  4. Введите число, меньше или равное 0 в параметре Предельные значения.

    Для параметра Предельные значения появится символ ошибки. Если вы наведете на него указатель или щелкните, то в подсказке всплывает ваше сообщение об ошибке.

  5. Проверьте, что список выбора Единицы измерения предельных значений обновился, в нем должны быть показаны единицы измерения в соответствии с выбранным значением параметра Режим передвижения.
    1. Выберите значение для параметра Сеть.

      Подсказка:
      Если вы используете данные из этого руководства, используйте набор сетевых данных SanFrancisco.gdb/Transportation/Streets_ND для параметра Сеть. Вы можете использовать путь каталога к набору сетевых данных или можете сначала добавить его на карту и использовать его представление слоя в качестве входных данных для инструмента.

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

    2. Выберите значение для параметра Режим передвижения.

      Если параметр Режим передвижения пустой, то параметр Единицы измерения предельных значений не содержит списка для выбора. Если значение введено для параметра Режим передвижения, то список выбора для параметра Единицы измерения предельных значений автоматически обновится, в нем будут показаны единицы измерения времени или расстояния (или только одна опция для Прочее).

Запуск инструмента

Вы создали и настроили инструмент-скрипт, написали код инструмента и настроили проверку инструмента. Теперь он готов к запуску и может использоваться как любой другой инструмент геообработки. Помимо запуска инструмента с панели Геообработка вы можете добавить его в модель, вызвать из скрипта Python, а также опубликовать его как веб-инструмент.

  1. Если необходимо, откройте инструмент, дважды щелкнув его на панели Каталог.
  2. Выберите подходящие опции для параметров инструмента.

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

    Подсказка:
    Если вы используете предоставленные учебные данные, используйте наборы данных в базе геоданных SanFrancisco.gdb, чтобы протестировать инструмент. Точечный класс объектов пожарных стаций, SanFrancisco.gdb/Analysis/FireStations, можно использовать в качестве параметра Входные пункты обслуживания, а набор сетевых данных SanFrancisco.gdb/Transportation/Streets_ND в качестве параметра Сеть. Вы можете использовать пути каталога к данным, или вы можете сначала добавить данные на карту и использовать слои в качестве входных данных для инструмента. Подходящим предельным значением при моделировании зоны обслуживания пожарной стации будет от 2 до 4 минут.

  3. Щелкните кнопку Запустить, расположенную внизу инструмента.

    Инструмент успешно отработает и добавит полигональный слой на карту.

    Примечание:
    При работе инструмента могут возникнуть сообщения с предупреждениями.