Обновление и исправление источников данных

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

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

Использование функции updateConnectionProperties

Два обязательных параметра функции updateConnectionProperties:

  • current_connection_info - Строка, представляющая собой путь к рабочей области либо словарь Python, содержащий свойства подключения к источнику, который вы собираетесь удалять.
  • new_connection_info - Строка, представляющая собой путь к рабочей области либо словарь Python, содержащий свойства подключения с информацией о новом источнике.

Функцию updateConnectionProperties можно рассматривать как функцию поиска и замены, с помощью которой вы заменяете параметр current_connection_info параметром new_connection_info. Этими параметрами могут быть либо полный путь к рабочей области, частичная строка, словарь, содержащий свойства соединения, частичный словарь, который определяет конкретные ключи, либо путь к файлу подключения к базе данных (.sde). Если в current_connection_info, используется пустая строка или None, все свойства подключения будут заменены на new_workspace_info, в зависимости от значения параметра validate.

Подсказка:

Не включайте имена набор классов объектов базы геоданных в параметры current_connection_info или new_connection_info. Наборы классов являются частью рабочей области.

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

По умолчанию, метод updateConnectionProperties обновляет источник данных, только если new_connection_info является допустимым источником данных. Если параметру validate задано значение False, то источник данных устанавливается в данное местоположение не зависимо, существует он или нет. Это может оказаться полезным в тех сценариях, в которых необходимо обновить источники данных до создания самих данных. В этих случаях данные являются поврежденными в связанных картах.

Если при замене параметра current_connection_info на параметр new_connection_info в функции updateConnectionProperties совпадений не найдено, ваш скрипт может завершиться, но ничего не будет обновлено.

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

Общие примеры updateConnectionProperties

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

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\Historic_Data\Yosemite.gdb',
                                    r'C:\Projects\YosemiteNP\New_Data\Yosemite.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. Следующий пример очень похож на приведенный выше, но для обновления папки, в которой находятся данные, используются строки частичного пути. В этом примере все вхождения Historic_Data в пути к рабочей области будут заменены на New_Data. Убедитесь, что при использовании частичной строки она не повторяется в пути несколько раз. Ожидаемые результаты могут быть не получены. В качестве альтернативы вы можете использовать строки полного пути вместо строк частичного пути.

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(current_connection_info='Historic_Data',
                                    new_connection_info='New_Data')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. В следующем примере заменяется подключение персональной базы геоданных на подключение файловой базы геоданных с использованием частичного пути для всех слоев и таблиц на карте:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = aprx.listMaps("Yose*")[0]
    m.updateConnectionProperties(current_connection_info='Background.mdb',
                                 new_connection_info='Background_fGDB.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. Следующий пример ссылается на слой на карте и использует эти свойства подключения для обновления свойств подключения для того же слоя в файле слоя, который не был обновлен с новым источником данных:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = aprx.listMaps('Yose*')[0]
    lyr = m.listLayers('Ranger Stations')[0]
    lyrFile = arcpy.mp.LayerFile(r'C:\Projects\YosemiteNP\LYRXs\Yosemite\OperationalLayers.lyrx')
    
    for l in lyrFile.listLayers():
      if l.name == 'Ranger Stations':
        l.updateConnectionProperties(l.connectionProperties, lyr.connectionProperties)
    
    lyrFile.save()
  5. В этом примере класс пространственных объектов перемещается в новую файловую базу геоданных. Скрипт выполняет поиск по всем потерянным слоям в проекте, который ссылается на класс пространственных объектов. Затем он обновляет источник данных слоя до новой файловой базы геоданных.

    import arcpy, os
    
    featureClass = 'Boundary'
    oldFileGDB = r'C:\Projects\YosemiteNP\Yosemite.gdb'
    newFileGDB = r'C:\Projects\YosemiteNP\YosemiteNew.gdb'
    
    # Reference project
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    
    # Search for specific broken layers
    for m in aprx.listMaps():
        for lyr in m.listLayers():
            if lyr.isBroken:
                if lyr.supports("DATASOURCE"):
                    if lyr.dataSource == os.path.join(oldFileGDB, featureClass):
                        lyr.updateConnectionProperties(oldFileGDB, newFileGDB)
    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  6. В следующем примере все источники данных направляются в одну файловую базу геоданных, указав current_connection_info быть None. Это может быть полезно в ситуациях, когда несколько источников данных объединены в одну рабочую область.

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(None, r'C:\Projects\YosemiteNP\New_Data\Yosemite.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

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

  1. В следующем примере подключение к файловой базе геоданных заменяется на путь к файлу подключения (.sde) многопользовательской базы геоданных для всех слоев и таблиц в проекте:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\Vector_Data\Yosemite.gdb',
                                    r'C:\Projects\YosemiteNP\DBConnections\Server.sde')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. В следующем примере свойства подключения из файла подключения многопользовательской базы геоданных в параметре current_connection_info заменяются новым файлом подключения многопользовательской базы геоданных в параметре new_connection_info:

    Примечание:

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

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\DBConnections\TestGDB.sde',
                                    r'C:\Projects\YosemiteNP\DBConnections\ProductionGDB.sde')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. В следующем примере файл подключения многопользовательской базы геоданных заменяется на путь к файловой базе геоданных для всех слоев и таблиц в проекте:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\DBConnections\Server.sde',
                                    r'C:\Projects\YosemiteNP\Local_Data\YosemiteLocal.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. В следующем примере все источники данных направляются в одну многопользовательскую базу геоданных, указав для current_connection_info - None. Это может быть полезно в ситуациях, когда учетные данные слоев многопользовательской базы геоданных в проекте неизвестны или недоступны.

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(None, r'C:\Projects\YosemiteNP\DBConnections\Server.sde')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

Использование словаря connectionProperties

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

Хороший способ отобразить структуру словаря – использовать функцию pprint Python.

import arcpy, pprint
p = arcpy.mp.ArcGISProject('current')
m = p.listMaps()[0]
l = m.listLayers()[0]
pprint.pprint(l.connectionProperties)

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

{'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\Yosemite.gdb'}, 
 'dataset': 'RangerStations', 
 'workspace_factory': 'File Geodatabase'}

Указанный выше пример является самой базовой структурой. Возвращается словарь с тремя ключами. Значением для ключа connection_info является другой словарь, который содержит путь к database.

Вот несколько примеров использования словаря connectionProperties:

  1. Следующий пример обновляет имя набора данных источников данных с RangerStations на RangerStationsNew. Он также изменяет базу данных с Yosemite.gdb на YosemiteNew.gdb.

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*").listLayers("Ranger Stations")[0]
    find_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\Yosemite.gdb'}, 
                 'dataset': 'RangerStations', 
                 'workspace_factory': 'File Geodatabase'}
    replace_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\YosemiteNew.gdb'}, 
                    'dataset': 'RangerStationsNew', 
                    'workspace_factory': 'File Geodatabase'}
    lyr.updateConnectionProperties(find_dict, replace_dict)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. Приведенный выше скрипт также можно переписать следующим образом:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*").listLayers("Ranger Stations")[0]
    cp = lyr.connectionProperties
    cp['connection_info']['database'] = 'C:\\Projects\\YosemiteNP\\Data\\YosemiteNew.gdb'
    cp['dataset'] = 'RangerStationsNew'
    lyr.updateConnectionProperties(lyr.connectionProperties, cp)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. Словарь connectionProperties также можно использовать для обновления файловых источников данных, таких как шейп-файлы, растровые файлы и т.д. В следующем примере изменяется источник данных слоя, чтобы он указывал на новый шейп-файл в другой папке.

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps('Main*').listLayers('RoadsShp')[0]
    cp = lyr.connectionProperties
    cp['connection_info']['database'] = 'C:\\Projects\\YosemiteNP\\Data_New'
    cp['dataset'] = 'NewRoads.shp'
    lyr.updateConnectionProperties(lyr.connectionProperties, cp)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

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

Ниже приводится пример словаря connectionProperties источника данных многопользовательской базы геоданных для слоя:

{'connection_info': {'authentication_mode': 'OSA',                     
                     'database': 'TestDB',                     
                     'db_connection_properties': 'TestServer',                     
                     'dbclient': 'sqlserver',                     
                     'instance': 'sde:sqlserver:TestServer',                     
                     'password': '*********',                     
                     'server': 'TestServer',                     
                     'user': 'User',                     
                     'version': 'sde.DEFAULT'}, 
'dataset': 'TestDB.USER.RangerStations', 
'workspace_factory': 'SDE'}

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

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

import arcpy
aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
find_dict = {'connection_info': {'db_connection_properties': 'TestServer',
                                 'instance': 'sde:sqlserver:TestServer',
                                 'server': 'TestServer'}}
replace_dict = {'connection_info': {'db_connection_properties': 'ProdServer',
                                    'instance': 'sde:sqlserver:ProdServer',
                                    'server': 'ProdServer'}}
aprx.updateConnectionProperties(find_dict, replace_dict)
aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

Использование словаря connectionProperties с соединениями

Словарь connectionProperties также покажет свойства любых соединений, которые присутствуют на слое. Любое из этих свойств может быть изменено.

В приведенном ниже примере показан словарь connectionProperties источника данных на основе файлов с одним соединением:

{'cardinality': 'one_to_many',
 'destination': {'connection_info': {'database': 'C:\\Projects\\FGDB.gdb'},
                 'dataset': 'tabular_eco',
                 'workspace_factory': 'File Geodatabase'},
 'foreign_key': 'ECO_CODE',
 'join_forward': False,
 'join_type': 'left_outer_join',
 'primary_key': 'CODE',
 'source': {'connection_info': {'database': 'C:\\Projects\\FGDB.gdb'},
            'dataset': 'mex_eco',
            'workspace_factory': 'File Geodatabase'}}

В этом примере показан словарь connectionProperties источника данных на основе файлов с двумя соединениями:

{'cardinality': 'one_to_many', 
 'destination': {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\BackgroundData.gdb'},                 
                 'dataset': 'census2000',                 
                 'workspace_factory': 'File Geodatabase'}, 
 'foreign_key': 'State_Polygons.State_Name', 
 'join_forward': False, 
 'join_type': 'left_outer_join',
 'primary_key': 'STATE_NAME', 
 'source': {'cardinality': 'one_to_many',
            'destination': {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\BackgroundData.gdb'},
                            'dataset': 'census2010',                            
                            'workspace_factory': 'File Geodatabase'},
            'foreign_key': 'State_Name',            
            'join_forward': False,            
            'join_type': 'left_outer_join',            
            'primary_key': 'STATE_NAME',            
            'source': {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\BackgroundData.gdb'},
                       'dataset': 'State_Polygons',                       
                       'workspace_factory': 'File Geodatabase'}}}

Когда соединения связаны со слоем или таблицей, структура словаря connectionProperties изменяется. У вас больше нет тех же трех ключей корневого уровня, как вы видели в предыдущих примерах. Чтобы понять, почему это отличается, следует изучить то, как сохраняются соединения. Соединения являются вложенными. Например, если таблица 1 и таблица 2 соединены со слоем, таблица 1 соединена со слоем, а таблица 2 соединена с комбинацией слоя и таблицы 1. Словарь корневого уровня сначала описывает второе соединение. Для второго source соединения, можно отслеживать связь с исходным слоем и таблицей один.

Вот несколько примеров использования словаря connectionProperties с соединениями:

  1. В следующем примере изменяется внешний ключ соединения для определенного слоя:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\Mexico\MexicoEcology.aprx')
    mexLyr = aprx.listMaps('Layers')[0].listLayers('mex_eco')[0]
    conProps = mexLyr.connectionProperties
    conProps['foreign_key'] = 'ECO_CODE_NEW'
    mexLyr.updateConnectionProperties(mexLyr.connectionProperties, conProps)
    aprx.saveACopy(r"C:\Projects\Mexico\MexicoEcologyNew.aprx")
  2. Частичный словарь может также использоваться в методе updateConnectionProperties. В следующем примере изменяются свойства соединения для всех слоев в проекте, которые используют указанный внешний ключ:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\Mexico\MexicoEcology.aprx')
    aprx.updateConnectionProperties({'foreign_key': 'ECO_CODE'}, {'foreign_key': 'ECO_CODE_NEW'})
    aprx.saveACopy(r"C:\Projects\Mexico\MexicoEcologyNew.aprx")
  3. В следующем примере изменяется база данных и набор данных источника для основного слоя, к которому присоединяются обе таблицы, без изменения информации о подключении для соединений:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*").listLayers("State_Polygons")[0]
    conProp = lyr.connectionProperties
    conProp['source']['source']['connection_info']['database'] = 'C:\\Projects\\YosemiteNP\\Vector_Data\\Census.gdb'
    conProp['source']['source']['dataset'] = 'States'
    lyr.updateConnectionProperties(lyr.connectionProperties, conProp)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. В следующем примере будет создан список соединений всех соединений на всех слоях карты. В этом примере используется логика рекурсивной функции Python для обработки слоев, которые не имеют ни одного соединения, или любого количества соединений:

    import arcpy
    
    def ListJoinsConProp(cp, join_count=0):
        if 'source' in cp:
            if 'destination' in cp:
                print(' '*6, 'Join Properties:')
                print(' '*9, cp['destination']['connection_info'])
                print(' '*9, cp['destination']['dataset'])
                join_count += 1
                return ListJoinsConProp(cp['source'], join_count)
        else:
            if join_count == 0:
                print(' '*6, '- no join')
    
    aprx = arcpy.mp.ArcGISProject(r"C:\Projects\Mexico\MexicoEcology.aprx")
    m = aprx.listMaps()[0]
    for lyr in m.listLayers():
        print(f"LAYER: {lyr.name}")
        if lyr.supports("dataSource"):
            cp = lyr.connectionProperties
            if cp is not None:
                ListJoinsConProp(cp)
  5. В следующем примере будут отображаться свойства подключения слоев на карте. Аналогично примеру выше, в этом примере также используется логика рекурсивной функции Python для обработки слоев, которые не имеют ни одного соединения, или любого количества соединений:

    import arcpy
    
    def ConPropsWithJoins(cp):
        if 'source' in cp:
            return ConPropsWithJoins(cp['source'])
        else:
            print(' '*6, 'database:', cp['connection_info']['database'])
            print(' '*6, 'dataset:', cp['dataset'])
            print(' '*6, 'workspace_factory:', cp['workspace_factory'])
    
    aprx = arcpy.mp.ArcGISProject(r"C:\Projects\Mexico\MexicoEcology.aprx")
    m = aprx.listMaps()[0]
    for lyr in m.listLayers():
        print(f"LAYER: {lyr.name}")
        if lyr.supports("dataSource"):
            cp = lyr.connectionProperties
            if cp is not None:
                ConPropsWithJoins(cp)

Обновление источников данных через CIM

Начиная с версии ArcGIS Pro 2.4, разработчики Python получили расширенный доступ к Картографической информационной модели (CIM) и смогут использовать намного больше настроек, свойств и возможностей, содержащихся в документе или проекте. Это может быть полезно при обновлении рабочих процессов источника данных. Более подробную информацию смотрите в разделе:

Если с помощью функции updateConnectionProperties сложно выполнить конкретный рабочий процесс источника данных, можно изменить структуру CIM слоя. В разделе Доступ к Python CIM описывается структура JSON объектной модели CIM. Понимание этой структуры позволит вам обновить CIM слоя.

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

"dataConnection" : {
  "type" : "CIMFeatureDatasetDataConnection",
  "workspaceConnectionString" : "DATABASE=C:\\Projects\\YosemiteNP\\Yosemite.gdb",
  "workspaceFactory" : "FileGDB",
  "dataset" : "Parcels",
  "datasetType" : "esriDTFeatureClass"
}

Ниже приведены некоторые примеры использования CIM для обновления источников данных:

  1. Этот скрипт изменяет источник данных связи в слое.

    import arcpy
    
    # Specify the new relate properties
    newGDB = "FGDB2.gdb"
    newFeatureClass = "Cities2"
    newRelateName = "New Relate"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\USA.aprx')
    m = p.listMaps('Relate Map')[0]
    l = m.listLayers('States')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Get the first relate on the layer
    relate = lyrCIM.featureTable.relates[0]
    
    # Get the data connection properties for the relate
    dc = relate.dataConnection
    
    # Change the connection string to point to the new File Geodatabase
    dc.workspaceConnectionString = dc.workspaceConnectionString.replace("FGDB.gdb", newGDB)
    
    # Change the dataset name
    dc.dataset = newFeatureClass
        
    # Change the relate's name
    relate.name = newRelateName
    
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\New\USA.aprx")
  2. Следующий пример ссылается на слой САПР на карте. Затем он обновит слой, чтобы указать на новый файл САПР. Скрипт предполагает, что новый файл САПР находится в той же папке, что и предыдущий файл САПР.

    Примечание:

    Обновление источника данных для слоев САПР для указания на новый файл САПР требует изменения CIM. Однако просто изменить папку, в которой находится файл САПР, можно с помощью функции updateConnectionProperties.

    import arcpy
    
    aprx = arcpy.mp.ArcGISProject(r"C:\Projects\YosemiteNP\Yosemite.aprx")
    m = aprx.listMaps('CAD')[0]
    # Select the CAD sub layer to update
    lyr = m.listLayers('Parcels')[0]
    
    # Access layer CIM
    lyrCIM = lyr.getDefinition("V3")
    dc = lyrCIM.featureTable.dataConnection
    
    # Update the feature dataset with the new CAD file name 
    dc.featureDataset = "NewParcels.dwg"
    
    # Update layer CIM
    lyr.setDefinition(lyrCIM)
    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

Изменение набора данных слоя

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

  • Используйте словарь connectionProperties, доступный для классов Layer и Table.
  • Используйте доступ к Python CIM.

Использование словаря connectionProperties для изменения набора данных слоя

  1. Следующий пример обновляет имя набора данных источников данных с RangerStations на RangerStationsNew. Он также изменяет базу данных с Yosemite.gdb на YosemiteNew.gdb.

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*").listLayers("Ranger Stations")[0]
    find_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\Yosemite.gdb'}, 
                 'dataset': 'RangerStations', 
                 'workspace_factory': 'File Geodatabase'}
    replace_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\YosemiteNew.gdb'}, 
                    'dataset': 'RangerStationsNew', 
                    'workspace_factory': 'File Geodatabase'}
    lyr.updateConnectionProperties(find_dict, replace_dict)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. В следующем примере обновляется имя набора данных источника данных с PtsInterest на PointsOfInterest для слоев в проекте. Этот пример не меняет базу геоданных, в которой находится класс пространственных объектов. Скорее, он обновляет слои, чтобы они указывали на другой класс пространственных объектов в той же базе геоданных, используя частичный словарь.

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties({'dataset': 'PtsInterest'}, {'dataset': 'PointsOfInterest'})
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. В следующем примере выполняется поиск слоев в проекте, которые ссылаются на определенный класс пространственных объектов. Затем он обновляет имя набора данных источника данных с PtsInterest на PointsOfInterest.

    import arcpy
    
    oldDataset = 'PtsInterest'
    newDataset = 'PointsOfInterest'
    fGDB = r'C:\Projects\YosemiteNP\Yosemite.gdb'
    
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    
    for m in aprx.listMaps():
        for lyr in m.listLayers():
            if lyr.supports("DATASOURCE"):
                if lyr.dataSource == os.path.join(fGDB, oldDataset):
                    lyr.updateConnectionProperties({'dataset': oldDataset}, {'dataset': newDataset})
                    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

Использование CIM для изменения набора данных слоя

  1. Этот скрипт обновляет источник данных слоя до нового класса пространственных объектов в той же базе геоданных.

    import arcpy
    
    newFeatureClass = "UpdatedBoundary"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = p.listMaps('Park Map')[0]
    l = m.listLayers('Boundary')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Update the dataset
    lyrCIM.featureTable.dataConnection.dataset = newFeatureClass
        
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. Этот скрипт выполняет поиск по всем потерянным слоям в проекте для определенного класса пространственных объектов, который был переименован. Затем он обновляет источник данных слоя до нового класса объектов.

    import arcpy
    
    newFeatureClass = "UpdatedBoundary"
    
    # Reference project
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    
    # Search for specific broken layers
    for m in aprx.listMaps():
        for lyr in m.listBrokenDataSources():
            if lyr.supports("DATASOURCE"):
                if lyr.dataSource == r'C:\Projects\YosemiteNP\Yosemite.gdb\Boundary':
                    # Get the layer's CIM definition
                    lyrCIM = lyr.getDefinition('V3')         
                    # Update the dataset
                    lyrCIM.featureTable.dataConnection.dataset = newFeatureClass
                    # Set the layer's CIM definition
                    lyr.setDefinition(lyrCIM)
    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. Этот скрипт меняет источник данных слоя, в котором класс пространственных объектов и имена набора пространственных объектов отличаются между существующей и новой базами геоданных.

    import arcpy
    
    # Specify the new geodatabase properties
    newGDB = "UpdatedParcels.gdb"
    newFeatureClass = "UpdatedParcelsFC"
    newFeatureDataSet = "UpdatedParcelsFDS"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = p.listMaps('Parcels Map')[0]
    l = m.listLayers('Parcels')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Get the data connection properties for the layer
    dc = lyrCIM.featureTable.dataConnection
    
    # Change the connection string to point to the new File Geodatabase
    dc.workspaceConnectionString = dc.workspaceConnectionString.replace("Parcels.gdb", newGDB)
    
    # Change the dataset name
    dc.dataset = newFeatureClass
    
    # If the data is in a Feature Dataset, then update it 
    if hasattr(dc, "featureDataset"):
        dc.featureDataset = newFeatureDataSet
        
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. В некоторых рабочих процессах структура CIM нового источника данных отличается от существующей структуры, поэтому вам необходимо создать новый объект подключения данных CIM. В этом примере слой, который не входит в набор данных объектов, обновляется, чтобы ссылаться на класс объектов, который находится в этом наборе классов. Для этого необходимо создать новый объект подключения данных CIM, поскольку атрибут набора классов объектов не входит в существующую структуру слоя CIM. Обратите внимание, что вам не обязательно в точности задавать атрибут набора классов объектов в этом коде. Вам обязательно нужно указать только класс объектов, а набор классов объектов будет заполнен автоматически. Тот же код будет использоваться для обновления источника данных слоя, который находится в наборе классов объектов, на класс объектов, которого в этом наборе нет.

    import arcpy
    
    # Specify the new geodatabase properties
    newGDB = r'C:\Projects\Data\NewParcels.gdb'
    newFeatureClass = "UpdatedParcelsFC"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = p.listMaps('Parcels Map')[0]
    l = m.listLayers('Parcels')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Create a new CIM data connection
    dc = arcpy.cim.CreateCIMObjectFromClassName('CIMStandardDataConnection', 'V3')
    
    # Specify the geodatabase
    dc.workspaceConnectionString = f"DATABASE={newGDB}"
    
    # Specify the workspace type
    dc.workspaceFactory = "FileGDB"
    
    # Specify the dataset name
    dc.dataset = newFeatureClass
    
    # Set the new data connection to the layer's CIM featureTable
    lyrCIM.featureTable.dataConnection = dc
        
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")