Обновление и установление источников данных с помощью модуля arcpy.mapping (arcpy.mapping)

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

В целом, существует два типа методов, применяемых к классам MapDocument, Layer и TableView. Имена методов незначительно изменяются в зависимости от доступного класса и параметров.

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

Ниже приводятся несколько определений для объяснения терминов, используемых в этом документе:

Методы обновления и фиксирования источников данных

Заметки по общему использованию

  • Функция ListBrokenDataSources() полезна для определения поврежденных слоев или таблиц в документе карты или файле слоя.
  • Эти методы работают рекурсивно по всем слоям и таблицам. Это означает, что поиск и обновления выполняются также в соединенных и связанных таблицах (см. раздел «Известные ограничения», приведенный ниже).
  • Можно найти и заменить весь путь к рабочей области или его часть. Если следует заменить только часть пути, убедитесь, что строка является уникальной. Например, поиск только буквы C и замена ее на букву D для изменения буквы диска приведет к менее предсказуемым результатам, чем поиск r"C:\" и замена этой строки на r"D:\".
  • Использование имени слоя для обособления источника данных не является гарантированной защитой от случайной ошибки, так как возможно наличие нескольких источников данных с одним и тем же именем слоя. Может понадобиться использовать другие свойства слоя для его уникального обособления.
  • Не включайте имена наборов классов базы геоданных в путь к рабочей области. Наборы классов являются частью рабочей области. Если класс объекта преобразуется из изолированного класса объектов в набор классов базы геоданных, документ карты будет открываться без повреждения слоя.
  • Параметры пути к рабочему пространству не должны включать имя набора данных таблицы или слоя, поэтому многие из приведенных выше методов не будут работать при изменении имени набора данных слоя или таблицы. Метод replaceDataSource для объектов Layer и TableView работает в соответствии с этим же сценарием.
  • При переключении рабочих областей с помощью метода replaceWorkspaces имена наборов данных должны быть идентичными. Например, шейп-файл Highways.shp может быть перенаправлен в рабочую область файловой базы геоданных только в том случае, если имя набора данных в файловой базе геоданных также называется Highways. Если имена отличаются, используйте метод replaceDataSource для объектов Layer и TableView.
    • Если пустая строка ("") используется для параметра old_workspace_path и значение NONE используется для параметра old_workspace_type, все источники данных сопоставляются с новой рабочей областью. Это позволяет перенаправлять несколько рабочих областей в одну рабочую область с помощью одного метода. С ключевым словом NONE может использоваться только пустая строка.

Дополнительный параметр validate

  • Этот параметр позволяет проверить существование нового источника данных, прежде чем изменить или заменить источник данных слоя или таблицы.
  • Если для параметра validate задано значение True и новый источник данных не только существует, но и является допустимым, исходный источник данных будет обновлен до нового источника данных; в противном случае будет использоваться исходный источник данных и ничего не изменится.
  • Если для параметра validate задано значение False новый источник данных не должен являться допустимым, то есть он может быть еще не существующим. Это может оказаться полезным в тех сценариях, в которых необходимо обновить источники данных до создания самих данных. Обратите внимание, что в этих случаях данные будут отображаться поврежденными в связанных документах карт и файлах слоев.
    • При использовании методов findAndReplaceWorkspacePath или findAndReplaceWorkspacePaths параметр validate применяется к параметру replace_workspace_path.
    • При использовании метода replaceWorkspacePaths параметр validate применяется к параметрам new_workspace_path и new_workspace_type.
    • При использовании метода replaceDataSource параметр validate применяется к параметру dataset_name.

Работа с подключениями SDE

  • Путь к рабочей области для подключений SDE — это путь к файлу подключения к SDE (.sde). Можно предоставить полный путь к файлу или в случае наличия файла подключения в папке Подключения баз данных(Database Connections) можно использовать эту строку в пути, например: find_workspace_path=r" Database Connections \myConnectionFile.sde"
  • Сведения о файле подключения к SDE, используемые в скрипте, должны быть идентичны подключению SDE, которое использовалось для добавления данных в документ карты или в файл слоя. Например, в двух разных местах могут содержаться два идентичных файла подключения SDE. Если данные были добавлены на карту с использованием пути к первому файлу подключения, однако в скрипте используется путь ко второму файлу подключения, источники данных могут не обновиться ожидаемым образом.
    • Свойство dataSource для объектов Layer и TableView предоставляет способ определения пути, используемого в документа карты или в файле слоя. Используйте это значение для определения пути к файлу подключения SDE, который следует использовать. Пример:
      lyr.findAndReplaceWorkspacePath(find_workspace_path=lyr.dataSource, replace_workspace_path=r"C:\Newpath\To\SDE_ConnectionFile.sde")
      
  • При удалении сведений о пароле из подключений SDE, чтобы исключить их из документа карты или файла слоя, необходимо задать значение validate=False. Это необходимо сделать, так как при попытке использования файла подключения SDE, не содержащего все необходимые сведения для подключения, подключение, естественно, завершится со сбоем. Настройка validate=False приведет к принудительному использованию нового файла подключения, и пользователь должен будет ввести учетные данные для входа при открытии документа карты, содержащего данные SDE.

Известные ограничения

  • Наборы схематических данных не могут обновляться вследствие наличия в них скрытых таблиц.
  • Подключения к серверу базы данных, которые выполняются напрямую к базам данных SQL Server Express, в настоящее время не поддерживаются. В качестве обходного пути можно создать подключение базы пространственных данных к базе данных SQL Server Express и использовать его.
  • Соединения и связи, сопоставленные со слоями растров, обновляться не будут.
  • Запросы SQL не обновляются автоматически. Различные рабочие области (например, персональная и файловая базы геоданных) задействуют разный синтаксис SQL для запросов определения слоев, и этот синтаксис не обновляется автоматически. Синтаксис может быть исправлен путем обновления свойства definitionQuery объекта Layer. Доступны простые строковые функции Python, которые позволяют выполнить базовые операции по поиску и замене. Некоторые примеры приведены ниже:
    • В персональных базах геоданных имена полей заключаются в квадратные скобки ([]), а в файловых базах геоданных они заключаются в двойные кавычки ("").
    • Подстановочными символами для персональных баз геоданных являются звездочки (*) и знаки вопроса (?), тогда как для файловых геоданных — это символ процента (%) и подчеркивание (_).

    • Строковые поиски в персональных базах геоданных не зависят от регистра в отличие от зависящих от регистра поисках в файловых базах геоданных.

    • В персональных базах геоданных используются методы UCASE и LCASE для конвертации регистра строк. В файловых базах геоданных используются методы UPPER и LOWER.

    • Даты и время в персональных базах геоданных разделяются знаком фунта (#), а в файловых базах геоданных перед ними идет слово date.

  • Выражения надписей слоев также не обновляются автоматически. Их также придется изменить для поддержки необходимого синтаксиса SQL. Синтаксис может быть исправлен путем обновления свойств слоя LabelClass SQLQuery или expression.
  • Сохраненные выборки в рамках документа карты очищаются при обновлении источника данных слоя (это также применимо при использовании команды Задать источник данных (Set Data Source) в диалоговом окне Свойства слоя (Layer Properties) в ArcMap). В настоящее время для рассмотренной проблемы нет обходного пути, кроме как повторного создания вручную выборок объектов в документе карты.

Распространенные сценарии

Данные на основе файлов перемещаются в другую папку или расположены на другом сетевом диске

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

В этом сценарии данные были расположены непосредственно в папке C:\Project\Data, но были перемещены в подпапку с именем Data2. Этот скрипт обновляет отдельный документ карты.

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
mxd.findAndReplaceWorkspacePaths(r"C:\Project\Data", r"C:\Project\Data2")
mxd.saveACopy(r"C:\Project\Project2.mxd")
del mxd

Изменение локального пути на путь UNC

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

В этом сценарии локальный системный путь меняется на путь UNC. Этот скрипт обновляет все документы карт в папке.

import arcpy, os
folderPath = r"C:\Project"
for filename in os.listdir(folderPath):
    fullpath = os.path.join(folderPath, filename)
    if os.path.isfile(fullpath):
        basename, extension = os.path.splitext(fullpath)
        if extension.lower() == ".mxd":
            mxd = arcpy.mapping.MapDocument(fullpath)
            mxd.findAndReplaceWorkspacePaths(r"C:\Project\Data", r"\\ComputerName\Project\Data")
            mxd.save()
del mxd

Меняются свойства подключения SDE

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

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

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project_default.mxd")
mxd.findAndReplaceWorkspacePaths(r"C:\Project\Connection to Default.sde", 
                                 r"C:\Project\Connection to Version1.sde")
mxd.saveACopy(r"C:\Project\Project_V1.mxd")
del mxd

В этом сценарии пользователь хочет удалить сведения о пароле, сохраненные в документе карты. Источники данных в документе карты берутся из файла подключения SDE, где были сохранены сведения о пароле наряду с информацией о подключении. Затем пользователь создал новый файл подключения SDE к той же базе данных, однако на этот раз не сохранил сведения о пароле. В приведенном ниже скрипте для параметра validate указано значение False, что успешно удаляет сведения о пароле. После выполнения скрипта пользователь должен выполнить вход, чтобы открыть полученный документ карты.

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project_default.mxd")
mxd.findAndReplaceWorkspacePaths(r"C:\Project\Connection with password info saved.sde", 
                                 r"C:\Project\Connection with no password info saved.sde", False)
mxd.saveACopy(r"C:\Project\Project_NP.mxd")
del mxd

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

Некоторые распространенные сценарии включают миграцию данных, таких как шейп-файлы и персональные базы геоданных, в файловую базу геоданных или данных из файловой базы геоданных в корпоративное подключение SDE. Так как рабочие области базы геоданных имеют незначительные отличия, важно просмотреть раздел «Известные ограничения», который приведен выше, чтобы ознакомиться с дополнительными трудностями и вопросами, которые могут возникнуть.

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

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
mxd.replaceWorkspaces(r"C:\Project\Data", "SHAPEFILE_WORKSPACE", r"C:\Project\Data\Parcels.gdb", "FILEGDB_WORKSPACE")
mxd.replaceWorkspaces(r"C:\Project\Data\Transportation.mdb", "ACCESS_WORKSPACE", r"C:\Project\Data\Transportation.gdb", "FILEGDB_WORKSPACE")
mxd.saveACopy(r"C:\Project\Project2.mxd")
del mxd

Этот пример идентичен приведенному выше примеру за исключением того, что все источники данных перенаправляются в одну файловую базу геоданных. Различные типы рабочих областей могут быть перенаправлены в один тип рабочей области, если вместо параметра old_workspace_type используется значение NONE.

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
mxd.replaceWorkspaces("", "NONE", r"C:\Project\Data\BackgroundData.gdb","FILEGDB_WORKSPACE")
mxd.saveACopy(r"C:\Project\Project2.mxd")

В следующем сценарии все слои перенаправляются из персональной базы геоданных в файловую базу геоданных. Кроме того, здесь исправляются выражения SQL, предназначенные для свойства слоя definitionQuery и свойства класса надписей SQLQuery. Например, в персональных базах геоданных имена полей обрамляются квадратными скобками ([]), тогда как файловые базы геоданных используют двойные кавычки (""). Кроме того, заменяются подстановочные символы.

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
mxd.replaceWorkspaces(r"C:\Project\Data\Parcels.mdb", "ACCESS_WORKSPACE",
                       r"C:\Project\Data\Parcels.gdb", "FILEGDB_WORKSPACE")
for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DEFINITIONQUERY"):
        lyr.definitionQuery = lyr.definitionQuery.replace("[", "\"")
        lyr.definitionQuery = lyr.definitionQuery.replace("]", "\"")
        lyr.definitionQuery = lyr.definitionQuery.replace("*", "%")

    if lyr.supports("LABELCLASSES"):
        for lblClass in lyr.labelClasses:
            lblClass.SQLQuery = lblClass.SQLQuery.replace("[", "\"")
            lblClass.SQLQuery = lblClass.SQLQuery.replace("]", "\"")
            lblClass.SQLQuery = lblClass.SQLQuery.replace("*", "%")

mxd.saveACopy(r"C:\Project\Project2.mxd")
del mxd

Отдельные наборы данных перемещаются в новую папку

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

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

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DATASOURCE"):
        if lyr.dataSource == r"C:\Project\Data\Parcels.gdb\MapIndex":
            lyr.findAndReplaceWorkspacePath(r"Data", r"Data2")
mxd.saveACopy(r"C:\Project\Project2.mxd")
del mxd

Отдельные наборы данных перемещаются в набор классов объектов базы геоданных и из него

Наборы классов базы геоданных являются частью рабочей области, и их имена не должны быть включены в путь к рабочей области. Если класс объекта перемещается в набор классов объектов базы геоданных или из него в рамках одной рабочей области, ничего не следует делать в плане обновления документов карт или источников данных файлов слоев. Если набор данных перемещается в другую рабочую область, имеющую тот же тип рабочей области, следует предоставить путь к новой рабочей области без имени набора классов объектов базы геоданных. Если тип рабочей области отличается, использование метода findAndReplaceWorkspacePath для слоя не будет работать и необходимо будет использовать метод replaceDataSource.

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

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DATASOURCE"):
        if lyr.dataSource == r"C:\Project\Data\Parcels.gdb\MapIndex":
            lyr.findAndReplaceWorkspacePath(r"Parcels.gdb", r"Transportation.gdb")
mxd.saveACopy(r"C:\Project\Project2.mxd")
del mxd

Переименован класс объектов

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

В этом сценарии класс объектов был переименован из MajorRoads в Highways, что нарушает отдельные слои в документе карты или файле слоя. В сценарии будут оцениваться только поврежденные источники данных с использованием функции ListBrokenDataSources() и выполняться необходимые исправления.

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
for lyr in arcpy.mapping.ListBrokenDataSources(mxd):
    if lyr.supports("DATASOURCE"):
        if lyr.dataSource == r"C:\Project\Data\Transportation.gdb\MajorRoads":
            lyr.replaceDataSource(r"C:\Project\Data\Transportation.gdb", "FILEGDB_WORKSPACE", "Highways")
            lyr.name = "Highways"
mxd.saveACopy(r"C:\Project\Project2.mxd")
del mxd
5/10/2014