Приручаем Змею. Введение в Python и ArcPy

Введение в Python и ArcPy

Леонов А.Л., Esri CIS, (По материалам статьи “Charming the Snake”, ArcUser, Winter 2011)

 

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

Использование новой библиотеки ГИС-функций ArcPy, появившейся в ArcGIS 10, значительно облегчает написание скриптов для обычных ГИС-специалистов. Python может стать хорошим подспорьем в работе и для тех пользователей, которые с теплыми чувствами вспоминают времена, когда в качестве среды разработки предлагался простой язык Avenue (скриптовый язык, использовавшийся в ArcView 3.x), на котором были написаны сотни полезных пользовательских программ. Python до какой то степени похож на Avenue и имеет ряд схожих привлекательных черт: значительное число хорошо документированных классов и функций, простота загрузки скрипта в документ и его запуска, большое число примеров (в том числе и некоторые стандартные инструменты Геообработки), обмен кодом в виде простого текстового документа и, возможно самое важное – нет необходимости знать, что такое QueryInterface. Python широко используется разработчиками, имеет статус непатентованного, существует много дополнительных библиотек, расширяющих его функциональность. Это, например, статистический модуль NumPy, содержащий большое число математических функций, или библиотека GDAL, позволяющая работать со многими популярными растровыми форматами. Изучение Python поможет решать задачи автоматизации обработки и анализа пространственных данных с большей гибкостью и эффективностью и с учетом ваших специфических потребностей.

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

Конечно, сам скрипт не имеет большой практической ценности, однако основная цель статьи – описать ключевые моменты, используемые при создании скриптов Python. Особое внимание будет уделено тому как:

  • Подключить дополнительные библиотеки для их использования в скрипте.
  • Получить пользовательские параметры.
  • Выводить сообщения о стадиях выполнения скрипта.
  • Получить ссылку на текущий документ карты.
  • Запустить инструмент геообработки.
  • Получить доступ к объекту в документе карты (фрейм данных, слои, таблицы).
  • Создавать оператор ветвления и цикла.
  • Создавать, открывать и писать в файл.

Для выполнения поставленной задачи по практическому освоению основ применения Python вам понадобятся:

  • ArcGIS Desktop 10 (действующая лицензия ArcView, ArcEditor или ArcInfo)
  • Документ карты, содержащий не менее двух фреймов данных с несколькими слоями в каждом.
  • Скрипт для этого упражнения, MxdReport.py, который в запакованном виде можно скачать по ссылке dataplus.ru/Arcrev/Number_57/Script/MxdReport.zip.

Начало работы

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

Существует несколько способов выполнения кода на Python из ArcGIS. Окно Python, появившееся в ArcGIS 10, представляет собой диалоговое окно с командной строкой. Его можно использовать для выполнения отдельных строк кода Python или загрузки и выполнения скрипта целиком. Однако, для написания скриптов, например, такого как в этом упражнении, лучше всего подходит интегрированная среда разработки Python (IDE). Для Python доступно несколько IDE. Мы воспользуемся стандартной средой разработки Python IDLE, которая включена в ArcGIS 10. Надо выполнить следующую последовательность действий.

 


Рис. 1. Документ карты должен содержать заполненные поля: Заголовок, Описание и Автор.


Рис. 2. В свойства скрипта добавляем три параметра, используя значения из Таблицы 1.

 

 

  • Откроем ArcMap. Для этого упражнения выберем документ карты, содержащий несколько фреймов данных, каждый из которых должен содержать несколько слоев.
  • Убедимся в том, что в документе карты прописаны Заголовок, Описание и Автор (рис. 1). Для проверки этого перейдем к свойствам в открытом документе карты: Файл > Свойства Документа Карты. Не пропустите этот шаг.
  • В ArcMap откроем окно ArcToolbox, используя меню Геообработка > ArcToolbox.
  • Откроем окно ArcCatalog. Щелкнув правой кнопкой мыши на домашней папке (где сохранен проект) выберем Новый > Набор инструментов. Назовем новый Набор инструментов GetStart.
  • Щелкнем правой кнопкой на ArcToolbox, выберем Добавить набор инструментов и укажем на ранее созданный набор инструментов GetStart.
  • Используя Windows Notepad или другой текстовый редактор, создадим новый текстовый файл с названием MxdReport.py.
  • В ArcMap создадим новый скрипт внутри набора инструментов GetStart, щелкнув на него правой кнопкой мыши и выбрав Добавить > Скрипт.
  • В мастере Добавить скрипт заполним поля Имя – MxdReport и Подпись – Create MXD Report и нажмем Далее.
  • В область параметра Файл скрипта добавим текстовый файл MxdReport.py, перейдя к месту на диске, где он был ранее создан. Нажмем Далее.
  • Добавим три параметра скрипта в следующем порядке: Путь к папке с результатом, Упаковать карту, Отследить битые ссылки (рис. 2). Каждому из них зададим значения, указанные в Таблице 1. Жмем Готово.
  • Откроем скрипт MxdReport.py в редакторе IDLE, нажав правой кнопкой на только что созданном Create MXD Report и выбрав опцию Редактировать. IDLE редактор откроет два окна. Одно окно будет содержать файл MxdReport.py. Другое окно, с названием Python shell, предназначено для интерактивного запуска скриптов и команд Python. Это окно можно закрыть, так как в этом примере мы его использовать не будем.

 

Таблица 1. Параметры скрипта MxdReport.py.

Имя параметра Тип данных Значение по умолчанию
Путь к папке с результатом Папка C:Temp
Упаковать карту Булевы False
Отследить битые ссылки Булевы True

 

Подключаем модули расширения

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

import os

import sys

import arcpy

import arcpy.mapping as mapping

Модули os и sys содержат функции, которые будут необходимы скрипту для работы с файлами на диске. Библиотека ArcPy открывает доступ к инструментам геообработки ArcGIS. Модуль arcpy.mapping содержит функции для работы с документом карты и объектами, размещенными на ней.

Получаем пользовательские параметры

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

outDir = arcpy.GetParameterAsText(0)
packageMap = arcpy.GetParameter(1)
checkBrokenLayers = arcpy.GetParameter(2)

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

Получаем ссылку на текущий документ карты

Чаще всего целью выполнения скрипта является текущий документ. Как только получена ссылка на текущий документ, скрипт получает доступ ко всем вложенным объектам, содержащимся в документе. Ссылка на документ карты открывает доступ к фреймам данных, слоям и таблицам, содержащимся в карте. Добавим строку кода, приведенную ниже, которая получает ссылку на текущий документ карты и сохраняет ее в переменной с названием mxd.

mxd = mapping.MapDocument(‘Current’)

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

Получаем доступ к файлу на диске

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

reportPath = outDir + ‘\’ + mxd.title + ‘.txt’

Оператор + используется для соединения строк в Python. Создаваемый файл с отчетом будет иметь такое же название, как и Заголовок карты (задается в свойствах документа карты) с добавленным расширением txt.

Используем функцию open для открытия файла:

reportFile = open(reportPath, ‘w’)

Функция open принимает два аргумента: имя файла и тип доступа к файлу. Существует несколько допустимых типов доступа к файлу: w – запись, r – чтение, a – добавление в конец. Если файл существует, он будет перезаписан. Если же его нет, то он будет создан. Чтобы информировать пользователя о статусе выполнения скрипта, добавим следующую строку кода.

arcpy.AddMessage(‘Пишем отчет в ‘.decode(‘windows-1251’) + reportPath)

Это сообщение появится в окне результатов выполнения инструментов геообработки.

Получаем информацию о карте

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

reportText = ‘Название: ‘ + mxd.title.encode(‘windows-1251’) + ‘n’

reportText += ‘Автор: ‘ + mxd.author.encode(‘windows-1251’) + ‘n’

reportText += ‘Описание: ‘ + mxd.description.encode(‘windows-1251’) + ‘n’

reportText += ‘~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~’ + ‘n’

Управляющая последовательность символов n означает возврат каретки. Комбинация символов += обозначает сокращенную команду, выполняющую присоединение текста к концу строки (например, reportText = reportText + «новый текст»). Метод encode(‘windows-1251’) превращает строку в набор символов вида Unicode, после чего преобразует ее в нужную кодировку (в этом примере windows-1251).

Напишем простое выражение с использованием оператора ветвления

Во всех языках программирования термин “ветвление” предполагает возможность принимать решения внутри кода. Примером может служить оператор IF/THEN, который обеспечивает выполнение определённой команды (набора команд) только при условии истинности логического выражения. Используем оператор ветвления для проверки того, хочет ли пользователь создать пакет карты:

if packageMap:

Во многих языках программирования форматирование текста используется для того чтобы сделать код более читаемым. В Python форматирование текста кода имеет функциональное назначение. Оно осуществляется путем выделения блоков кода с помощью отступов (пробелов или табуляций), поэтому в Питоне отсутствуют операторные скобки begin/end или фигурные скобки. С одной стороны, такое форматирование текста позволяет сократить количество строк и символов в программе и приучает к «хорошему» стилю программирования. С другой стороны, поведение и даже корректность программы может зависеть от начальных пробелов в тексте.

Код с отступом после оператора ветвления означает, что он будет выполнен при подтверждении истинности условия. Поверить форматирование можно, сверившись с загруженным MxdReport.py. Добавим код, который присваивает переменной путь к папке, где будет создаваться пакет карты.

packagePath = outDir + ‘\’ + mxd.title.replace(‘.’, ‘_’) + ‘.mpk’

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

if (os.path.exists(packagePath)):
arcpy.AddMessage(‘Пакет Карты уже существует (‘.decode(‘windows-1251’) + packagePath + ‘)’)

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

Любой инструмент геообработки, доступный из ArcToolbox, может быть выполнен с использованием ArcPy. Для создания пакета карты мы выполним запуск инструмента геообработки PackageMap (Упаковать Карту), передав ему необходимые параметры. Добавим альтернативный блок ELSE к созданному ранее оператору ветвления. Добавим сообщение, информирующее пользователя о том, что создается пакет карты.

else:

arcpy.AddMessage(‘Создаем Пакет Карты (‘.decode(‘windows-1251’) + packagePath + ‘)’ )

Используем ArcPy для вызова инструмента геообработки PackageMap:

arcpy.PackageMap_management(mxd.filePath, packagePath)

В качестве аргументов функция PackageMap_management требует путь к документу карты и путь к папке, где будет создан пакет карты.

Пройдем все фреймы данных, существующие в документе карты

В Python можно использовать оператор цикла, основанный либо на условии (цикл WHILE), либо использующий совокупность значений (цикл FOR). Используем функцию mapping.ListDataFrames для получения списка всех фреймов данных карты.

Убедимся, что начинаем вводить код в редакторе с крайней левой позиции (т.е. без отступа), чтобы он выполнялся вне предыдущего оператора ветвления:

dataFrames = mapping.ListDataFrames(mxd, »)

При вызове функции ListDataFrames нужно указать следующие аргументы: документ карты (или путь к нему) и строка с групповыми символами, позволяющая фильтровать фреймы данных на основе их названий (например, Адм*). Функция возвращает список фреймов данных, содержащихся в текущем документе карты. Начнем цикл FOR по каждому фрейму данных из полученного списка:

for frame in dataFrames:

Добавим информацию о фрейме данных в переменную reportText. Как и в случае с оператором ветвления, код, который будет выполняться внутри цикла, должен вводиться с отступом после оператора FOR.

reportText += ‘nФрейм данных: ‘ + frame.name.encode(‘windows-1251’) + ‘n’

reportText += ‘Пространственная привязка: ‘ + frame.spatialReference.name.encode(‘windows-1251’) + ‘n’

Цикл по всем слоям в каждом фрейме данных

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

layers = mapping.ListLayers(mxd, », frame)
i = 0
for lyr in layers:

reportText += ‘tСлой ‘ + str(i) + ‘: ‘ + lyr.name.encode(‘windows-1251’) + ‘n’

i += 1

Функция ListLayers похожа на ListDataFrames. Она возвращает список слоев. Функция str конвертирует значение (например, целое число) в строку.

Находим слои, потерявшие связь с данными

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

if checkBrokenLayers:

arcpy.AddMessage(‘Проверяем на отсутствующие источники данных’.decode(‘windows-1251’))

brokenList = mapping.ListBrokenDataSources(mxd)

reportText += ‘nНайдено ‘ + str(len(brokenList)) + ‘ слоев без источника данных.n’

for broken in brokenList:

reportText += ‘t- ‘ + broken.name.encode(‘windows-1251’) + ‘n’

Функция LEN возвращает число объектов в списке.

Записываем файл на диск

На этом этапе весь отчет содержится в переменной reportText. Теперь всё, что требуется – это записать такую строку в созданный ранее файл с отчетом. После записи текста, содержащегося в reportText, в файл мы должны закрыть его и удалить все переменные mxd, использованные в этом коде.

reportFile.write(reportText)
reportFile.close()
del mxd

Тестируем скрипт

Теперь скрипт готов к выполнению. Проделаем следующее.

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

Заключение

С появлением в ArcGIS 10 библиотеки ArcPy использовать язык Python стало значительно проще. Доступность и относительная простота Python делает его мощным инструментом для воплощения многих задач, актуальных для ГИС-специалистов.

В помощь начинающим освоение Python можно порекомендовать перевод книги «В глубь языка Python», доступный на сайте http://ru.diveintopython.org/toc.html. Также может оказаться полезным учебник по Python 2.6 на русском языке, опубликованный на сайте http://ru.wikibooks.org/wiki/Учебник_Python_2.6. Кстати, по-английски Python произносится как Пайфон.