Python CIM 访问

arcpy.mp 模块是一个粗粒度 Python API,旨在提供对许多常见地图自动化任务的访问权限。 它包含一组不同的公开类、类属性和帮助程序函数,但不提供对 ArcGIS Pro 中的所有可用属性、设置和功能的访问权限。 一个原因是保持 API 简化、简单且易于管理。 另一个原因是 ArcGIS Pro 的当前开发速度太快,API 无法跟上。 可能需要一个或多个版本,然后才能通过托管的 API 进行访问。 从 ArcGIS Pro 2.4 开始,Python 开发人员可以对制图信息模型 (CIM) 进行细化访问,并可以访问工程或文档中永久保留的更多设置、属性和功能。 从 ArcGIS Pro 1.1 开始,.NET SDK 开发社区已具有 CIM 访问权限,现在它可供 Python 开发社区使用。

警告:

以下几个部分介绍了使用 CIM 可以执行的操作,但了解不应该执行的操作同样重要。 在尝试修改对象的 CIM 文档之前,建议阅读“谨慎修改 CIM”部分。

什么是 CIM

CIM 是 Esri 制图信息模型。 它是一个地图内容规范,用于记录在保存、读取、引用或打开时如何永久保留描述不同项目组件的信息。 该规范以 JSON 表示,适用于 ArcGIS 应用程序和 API 中的地图、场景、布局、图层、符号和样式。

无论其首字母缩略词为何,都不要认为 CIM 仅限于制图设置。 通过 CIM 向这些类公开的功能远远不止如此,下面的示例演示了其中一些扩展功能。

需要了解对象的 JSON 结构才能成功修改对象的 CIM 定义。 JSON 的结构与向 arcpy.mp 模块公开的 CIM 对象模型并行。 访问点通过 arcpy.mp图层地图布局。 所有这些类均可以保存为 JSON 文件格式:.lyrx.mapx.pagx。 可在编辑器中打开这些文件,并查看如何组织和永久保留信息。

警告:
不要直接编辑这些文件。 请使用 API。

修改 CIM 定义

基本工作流如下:使用要修改的特定对象上的 getDefinition() 方法返回对象的 CIM 定义,对 CIM API 进行适当的更改,然后使用 setDefinition() 方法将更改推送回同一对象。 要返回对象的 CIM 定义,必须指定 cim_version。 Esri 遵循语义版本规范。 这意味着,在允许突破性 API 更改的下一个主要版本(例如,3.0)之前,与 cim_version 搭配使用的值为 'V2'。 发布 3.0 之后,新 'V3' 枚举值将可用。 如果可能在新版本中引入突破性更改,Python 脚本作者可通过该值控制脚本执行期间使用的 CIM 版本。

返回 CIM 定义后,可以尝试通过查看其代码完成及其 intellisense 来导航其结构,或者可以使用各种 Python 语句来了解有关可用属性的详细信息。 要了解属性的组织方式以及如何针对每个类导航 CIM 对象模型,一个非常有用的方法就是创建相应的导出文件。 例如,可以将地图保存到 .mapx 文件,将图层保存到 .lyrx 文件,并将布局保存到 .pagx 文件。 所有这些导出文件均采用 JSON 格式,可以在编辑器中进行查看。 有时,如果将 *.***x 文件扩展名更改为 *.json,则编辑器可能会显示更好的格式。

示例 1:基本布尔值,根级别属性

下面是 CIMLayerDocument (*.lyrx) 的可用已修改根级别属性缩写列表的 JSON 表示。

{
  "type" : "CIMLayerDocument",
  "version" : "2.4.0",
  "layers" : [
    "CIMPATH=map/greatlakes.xml"
  ],
  "layerDefinitions" : [
    {
      "type" : "CIMFeatureLayer",
      "name" : "GreatLakes",
      "uRI" : "CIMPATH=map/greatlakes.xml",
      "useSourceMetadata" : true,
      "description" : "GreatLakes",
      "layerType" : "Operational",
      "showLegends" : true,
      "visibility" : true,
      "displayCacheType" : "Permanent",
      "maxDisplayCacheAge" : 5,
      "showPopups" : true,
      "serviceLayerID" : -1,
      "autoGenerateFeatureTemplates" : true,
      "featureElevationExpression" : "0",
      "featureTable" : {
      "htmlPopupEnabled" : true,
      "selectable" : true,
      "featureCacheType" : "Session",
      "scaleSymbols" : true,
      "snappable" : true

基本元数据在描述文档和图层的文件的顶部显示。 同时存在许多根级别 layerDefinitions 属性。 该列表取决于对象中永久保留的设置。 IDE 代码完成显示的属性将显示比在上面的 JSON 文件中看到的选项更多的选项。 这是因为 JSON 文件仅存储当前设置,而不是所有可能的设置。 如何有意缩写 JSON 文件的一个示例是布尔值。 仅当前设置为 true 的属性才会出现在 JSON 文件中。 例如,代码完成应显示其他属性,例如 expandedshowMapTips,但由于它们目前设置为 false,因此不会出现在上面的 JSON 文件中。

以下 arcpy.mp 脚本将修改 CIM 图层对象 (l_cim) 的一些根级别属性。 selectable 属性将出现在上面的 JSON 文件中,因为其当前值为 true,但它在 Python 脚本中将设置为 FalseshowMapTipsexpanded 属性当前不会出现在 JSON 文件中,因为二者的值为 false,但它们将设置为 True。 如果将图层保存到另一个图层文件 (*.lyrx),则 JSON 文件中将显示相应的更改。

# Reference a project, map, and layer using arcpy.mp
p = arcpy.mp.ArcGISProject('current')
m = p.listMaps('Map')[0]
l = m.listLayers('GreatLakes')[0]

# Return the layer's CIM definition
l_cim = l.getDefinition('V2')

# Modify a few boolean properties
l_cim.showMapTips = True  #Turn on map tips for bubble tips to appear
l_cim.selectable = False  #Set the layer to not be selectable
l_cim.expanded = True     #Expand the Layer in the Contents pane

# Push the changes back to the layer object
l.setDefinition(l_cim)

# Save changes
p.save()

示例 2:修改字段属性

上面的 JSON 和 Python 示例相对简单,因为仅修改了根级别属性。 可以根据每个对象定义的复杂性及其嵌套功能集来嵌套 CIM 对象模型。 一个对象可以具有零到多个设置为其他对象的成员,且这些对象也可以具有对其他对象的依赖性。 每个相关对象都将在 JSON 结构中缩进。 缩进的所有内容同样适用于该 CIM 对象。 您可通过在 JSON 编辑器中查看 JSON 结构来展开和折叠该对象等级。 使用 JSON 文件的另一个优势是可用于搜索属性,然后使用 CIM API 确定如何访问嵌套结构。

此示例深入到比根级别低一级的对象模型。 如果将上方 JSON 示例中的 featureTable 成员展开,则您将看到其他成员。 CIMFeatureTable 类具有一个名为 fieldDescriptions 的成员,该成员将获取 CIMFieldDescription 类的列表。 根据字段类型,该类可能具有将 CIMNumericFormat 类作为值的 numberFormat 成员。 请注意如何很好地使用缩进来组织各个级别的相关类。

"featureTable" : {
        "type" : "CIMFeatureTable",
        "displayField" : "NAME",
        "editable" : true,
        "fieldDescriptions" : [
          {
            "type" : "CIMFieldDescription",
            "alias" : "OBJECTID",
            "fieldName" : "OBJECTID",
            "numberFormat" : {
              "type" : "CIMNumericFormat",
              "alignmentOption" : "esriAlignRight",
              "alignmentWidth" : 0,
              "roundingOption" : "esriRoundNumberOfDecimals",
              "roundingValue" : 0
            },
            "readOnly" : true,
            "visible" : true,
            "searchMode" : "Exact"
          },

例如,常见的请求是能够修改表的字段别名或可见性,尤其是在使用 MakeFeatureLayer 动态创建表时。 使用托管的 API 无法完成此操作。 此脚本使用 CIM 访问可从中设置 aliasvisible 属性的要素图层 featureTable 对象及其 fieldDescriptions 对象。 Python 语法遵循 CIM 对象模型,其中每个点基于 JSON 结构的缩进显示下一个对象的属性集。

# Reference a project, map, and layer using arcpy.mp
p = arcpy.mp.ArcGISProject('current') 
m = p.listMaps('Map')[0]
lyr = m.listLayers('GreatLakes')[0]

# Get the layer's CIM definition
cim_lyr = lyr.getDefinition('V2')

# Make changes to field properties
for fd in cim_lyr.featureTable.fieldDescriptions:
    if fd.fieldName == "OBJECTID":
        fd.visible = False            #Do not display this field
    if fd.fieldName == "Shape_Area":
        fd.alias = "Area (hectares)"  #Change field alias

# Push the changes back to the layer object
lyr.setDefinition(cim_lyr)

示例 3:修改图层符号系统

此示例显示了 CIM 对象模型的嵌套方式,同时显示了 CIM 级别访问的优势。 托管的 arcpy.mp API 对渲染器和属性深度的访问权限有限。 它只能修改符号的默认图层的简单属性。 但是,CIM 可以访问具有多个图层的符号。 以下屏幕截图显示了应用程序中 arcpy.mp API 无法使用的设置:

面要素图层的符号系统窗格。

这是一个经过编辑的简化 JSON 文件,仅显示图层符号系统的渲染器信息。 renderer 具有类型为 CIMSimpleRenderersymbol 以及类型为 CIMPolygonSymbolsymbol。 面符号具有两个 symbolLayersCIMSolidStrokeCIMSolidFill,二者都用于显示符号系统窗格中的可用属性。

"layerDefinitions" : [
    {
      "renderer" : {
        "type" : "CIMSimpleRenderer",
        "patch" : "Default",
        "symbol" : {
          "type" : "CIMSymbolReference",
          "symbol" : {
            "type" : "CIMPolygonSymbol",
            "symbolLayers" : [
              {
                "type" : "CIMSolidStroke",
                "effects" : [
                  {
                    "type" : "CIMGeometricEffectDashes",
                    "dashTemplate" : [ 5, 5],
                    "lineDashEnding" : "NoConstraint",
                    "controlPointEnding" : "NoConstraint"
                  }
                ],
                "enable" : true,
                "capStyle" : "Round",
                "joinStyle" : "Round",
                "lineStyle3D" : "Strip",
                "miterLimit" : 10,
                "width" : 3,
                "color" : {
                  "type" : "CIMRGBColor",
                  "values" : [0, 0, 0, 100]
                }
              },
              {
                "type" : "CIMSolidFill",
                "enable" : true,
                "color" : {
                  "type" : "CIMRGBColor",
                  "values" : [ 255, 127, 0, 100 ]
                }
              }

此 Python 代码使用 CIM 访问来修改图层的符号系统。 将修改两个符号图层。

# Reference a project, map, and layer using arcpy.mp
p = arcpy.mp.ArcGISProject('current')
m = p.listMaps('Trail Routes')[0]
lyr = m.listLayers('Loops')[0]

# Return the layer's CIM definition
cim_lyr = lyr.getDefinition('V2')

# Modify the color, width and dash template for the SolidStroke layer
symLvl1 = cim_lyr.renderer.symbol.symbol.symbolLayers[0]
symLvl1.color.values = [250, 250, 40, 50]
symLvl1.width = 8
ef1 = symLvl1.effects[0]    #Note, deeper indentation 
ef1.dashTemplate = [20, 30] #Only works if there is an existing dash template

# Modify the color/transparency for the SolidFill layer
symLvl2 = cim_lyr.renderer.symbol.symbol.symbolLayers[1]
symLvl2.color.values = [140, 70, 20, 20]

# Push the changes back to the layer object
lyr.setDefinition(cim_lyr)

谨慎修改 CIM

CIM 显示许多有用的功能,但稍不谨慎,事情就会出错。 应用程序和托管 API 旨在阻止您进行可能使应用程序处于受影响状态的更改。 CIM 显示了所有内容,因此可能会做出在应用程序中无法实现的冲突更改。 需要测试用于修改 CIM 的脚本。 确保应用程序不会在进行此类更改后作出奇怪的响应。 仅限于更改对其他设置没有依赖性的设置。

示例 1:无法更改空间参考

您可能认为更改地图空间参考很直接,因为 JSON 描述包含名为 spatialReference 的标记。

"mapDefinition" : {
    "type" : "CIMMap",
    "name" : "Map",
    "uRI" : "CIMPATH=map/map.xml",
    "metadataURI" : "CIMPATH=Metadata/a7afc904584d1037910b2cfe65fe94f8.xml",
    "useSourceMetadata" : true,
    "illumination" : {
    "layers" : [
    "standaloneTables" : [
    "defaultViewingMode" : "Map",
    "mapType" : "Map",
    "datumTransforms" : [
    "defaultExtent" : {
    "elevationSurfaces" : [
    "spatialReference" : {
      "wkid" : 4326,
      "latestWkid" : 4326
    },

如果您尝试仅修改地图的 wkidlatestWkid 属性,则无法获得预期结果。 这是因为应用程序中有许多其他部分与空间参考相关联,并且需要对地图的 CIM 进行许多更改才能使更改正常工作。 例如,对空间参考所做的更改也会影响基准转换、许多范围、裁剪几何等。 此类操作应在将作出所有适当更改的应用程序中或使用托管 API 进行。

示例 2:不要将应用程序置于奇怪状态

在此示例中,将在 CIM 中修改与图层标注属性关联的表达式引擎。 在下面的屏幕截图中,表达式引擎从默认的 Arcade 更改为 Python。 下图显示了其在 UI 中的外观以及 JSON 部分的显示方式。

要素图层的标注类表达式窗格。

"labelClasses" : [
        {
          "type" : "CIMLabelClass",
          "expression" : "$feature.NAME",
          "expressionEngine" : "Arcade",
          "featuresToLabel" : "AllVisibleFeatures",
          "maplexLabelPlacementProperties" : {
          "name" : "Class 1",
          "priority" : -1,
          "standardLabelPlacementProperties" : {
          "textSymbol" : {
          "useCodedValue" : true,
          "visibility" : true,
          "iD" : -1
        }

下面的 Python 脚本仅更改 expressionEngine,而不会更改 expression。 这会导致应用程序行为不规律。 例如,在运行下面的代码后,查看图层的标注属性时,expressionEngine 已正确设置为 Python,但 expression 仍以 Arcade 格式显示。 在用户界面中,当将表达式引擎更改回 Arcade 时,表达式将以 Python 格式显示,与预期格式相反。 要避免发生这种情况,需要更新 expressionEngineexpression 属性。

# Update the label expression engine from Arcade, the default, to Python.
# You must also update the expression otherwise the UI won't behave correctly after.

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps('Map')[0]
l = m.listLayers()[0]

l_cim = l.getDefinition()

lc = l_cim.labelClasses[0]
lc.expressionEngine = 'Python'    #From 'Arcade'
lc.expression = '[STATE_NAME]'    #From '$feature.STATE_NAME'

l.setDefinition(l_cim)

提示

有时,JSON 文件中的属性标记难以找到,因为标记名称不直观,或者它可以嵌套在对象模型中。 要解决此问题,一种方法是将值设置为真正唯一的值,并在 JSON 文件中搜索该值。 例如,将布局元素的宽度设置为 0.7777 或将 RGB 颜色设置为 111, 111, 111

您可能会在 JSON 文件中看到要更改的枚举值,但您不知道新的正确值应该是什么。 解决方案是在应用程序中设置正确的值,将对象保存到 JSON 导出文件,然后评估更新的值。

ArcGIS.Core.CIM 命名空间 .NET SDK API 参考帮助主题提供了每个类成员的 CIM 对象和文档列表。

创建 CIM 对象

在 2.5 之前的版本中,arpy.mp 模块只能使用托管的 API 创建或(更具体地说)克隆图形文本元素。 Python CIM 访问 API 过去仅允许您更改现有属性。 从版本 2.5 开始,出现了一种用于创建 CIM 类的新技术,可将其用于扩展在对象的 CIM 定义中显示的功能。 该函数名为 CreateCIMObjectFromClassName,且位于 arcpy.cim 模块中。 cim_class_name 参数是 CIM 类在 JSON 文件中显示的名称,且 cim_version 参数的用法与上面定义的 GetDefiniton 函数相同。 CreateCIMObjectFromClassName 将返回包含适当成员的对象,但不会自动创建其他对象依赖项。 例如,如果所创建类的成员需要将另一个类作为其值,则您需要再次执行该函数以生成该类。 必须对所有相关类和子类执行该过程;这可能需要付出大量努力。 该问题将在后面的示例中解决,我们先从一个简单的场景开始;在该场景中,只需创建一个对象即可完成解决方案。

注:

将不会自动导入 arcpy.cim 模块。 getDefinitionsetDefinition 方法将根据需要导入 CIM 模块。 如果您在 getDefinitionsetDefinition 之前调用了 CreateCIMObjectFromClassName,则必须显式导入 CIM 模块。

示例 1:单个类 - RGB 颜色

如果您插入新的默认地图并返回地图的 CIM backgroundColor,则该值将为 NoneType,原因是该值未在 CIM 中定义。 默认情况下,新地图的背景颜色将设置为“无颜色”。 您甚至都不会看到在 JSON 文件中定义该成员。 确定需要执行哪些操作的一种简单的方法就是:使用背景颜色创作地图,然后将更改前后的内容另存为地图文件 (.mapx) 并比较差异。 下图显示了左侧 JSON 更改之前和右侧 JSON 更改之后的屏幕截图。 请注意,在右侧,backgroundColor 成员已被插入到 mapTypebookmarks 成员之间。 CIM 对象在 JSON 中用双引号表示;该对象以字母 CIM 开头,后跟关键字“type”。 要设置地图的 backgroundColor,您需要创建一个颜色对象;在此示例中为 CIMRGBColor 对象。 该颜色可能已使用其他颜色模型进行了定义,且 CIM 对象 type 将有所不同。

将背景颜色插入到 JSON 文件中之前和之后结果的屏幕截图。

以下代码将创建一个 CIMRGBColor 类,用于设置地图的背景颜色。 请注意,您可能需要关闭底图或其他图层才能看到更改。

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps()[0]
m_cim = m.getDefinition('V2')        #Get the map's CIM definition

#Check to see if a background color exists, if not create a color
if m_cim.backgroundColor is None:
  RGBColor = arcpy.cim.CreateCIMObjectFromClassName('CIMRGBColor', 'V2')
  RGBColor.values = [115, 178, 255, 100]
  m_cim.backgroundColor = RGBColor   #Set the property to the new object
m.setDefinition(m_cim)               #Set the map's CIM definition

示例 2:单个类 - 空间地图系列

使用 CIM 创建空间地图系列几乎与创建 RGB 颜色一样简单。 空间地图系列也是单个对象,但它具有更多的属性。 下图显示了如何将空间地图系列保留在 JSON 文件中的屏幕截图。 indexLayerURI 是 CIM 独有的概念,不会在用户界面中作为一项设置显示出来。 URI 是保留在 CIM 中以确保引用唯一性的对象的唯一标识符。 对于图层,即使您更改图层名称,URI 也不会更改。 获取 indexLayerURI 值的唯一方法就是通过图层的 CIM 定义进行获取。

将空间地图系列插入到 JSON 文件中的结果的屏幕截图。

以下代码将创建一个 CIMSpatialMapSeries 类,用于为布局创作新的空间地图系列。 该示例中包括用于获取图层 URI 值的额外代码行。 注意,需要再次调用 get/setDefinition 函数,以确保内容窗格中的地图系列页面选项卡刷新。

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps('GreatLakes')[0]
l = m.listLayers('GreatLakes')[0]

l_cim = l.getDefinition('V2')         #Get layer's CIM / Layer URI
lURI = l_cim.uRI                      #Needed to specific the index layer 

lyt = p.listLayouts('GreatLakes')[0]
lyt_cim = lyt.getDefinition('V2')     #Get Layout's CIM definition

#Create CIM Spatial Map Series Object and populate its properties
ms = arcpy.cim.CreateCIMObjectFromClassName('CIMSpatialMapSeries', 'V2')
ms.enabled = True
ms.mapFrameName = "Great Lakes MF"
ms.startingPageNumber = 1
ms.currentPageID = 2
ms.indexLayerURI = lURI               #Index layer URI from Layer's CIM 
ms.nameField = "NAME"
ms.sortField = "NAME"
ms.sortAscending = True
ms.scaleRounding = 1000
ms.extentOptions = "BestFit"
ms.marginType = "Percent"
ms.margin = 10

lyt_cim.mapSeries = ms                #Set new map series to layout
lyt.setDefinition(lyt_cim)            #Set the Layout's CIM definition

#Force a refresh of the layout and its associated panes
lyt_cim = lyt.getDefinition('V2')
lyt.setDefinition(lyt_cim)

示例 3:一个相关类 - 书签地图系列

前两个示例显示了具有简单属性的 CIM 类。 如本主题前面所述,有时新创建的 CIM 对象将具有依赖于其他 CIM 对象的属性值。 CreateCIMObjectFromClassName 函数不会自动创建所有相关子类,且您也可以使用相同的方法来创建那些相关对象。 CIMBookmarkMapSeries 类就是一个很好的例子。 该类具有一个名为 pages 的属性,且该属性为单个 CIMBookmarkMapSeriesPage 对象的集合。 以下是如何将“书签地图系列”保留在 JSON 文件中的屏幕截图。 您将发现 CIMBookmarkMapSeriesPage 类嵌套在 CIMBookmarkMapSeries 类中。 每个页面均由其 bookmarkName 进行定义,且每个书签都有一个 mapURI,即该书签所关联地图的唯一标识符。

将书签地图系列插入到 JSON 文件中的结果的屏幕截图。

以下代码将创建一个 CIMBookmarkMapSeries 类和多个 CIMBookmarkMapSeriesPage 类,用于为布局创作新的书签地图系列。 书签地图系列需要引用地图的 URI 且该 URI 与图层的 URI 类似,您只能从地图的 CIM 定义中获取该值。

p = arcpy.mp.ArcGISProject('current')
m = p.listMaps('Map')[0]

#Get map URI from map CIM
m_cim = m.getDefinition('V2')           
mURI = m_cim.uRI

#Get Layout CIM
lyt = p.listLayouts('No Map Series')[0] 
lyt_cim = lyt.getDefinition('V2')

#Create the CIMBookmarkMapSeriesPage(s) necessary for creating the CIMBookmarkMapSeries
#Iterate through each bookmark in the order you want them added to the map series
bkmkNames = ["Northeast", "Southeast", "Northwest",]  
pageList = []
for bkmk in bkmkNames:
  bkmkPage = arcpy.cim.CreateCIMObjectFromClassName('CIMBookmarkMapSeriesPage', 'V2')
  bkmkPage.bookmarkName = bkmk
  bkmkPage.mapURI = mURI                
  pageList.append(bkmkPage)             

#Create a Bookmark Object and populate
bmMS = arcpy.cim.CreateCIMObjectFromClassName('CIMBookmarkMapSeries', 'V2')
bmMS.enabled = True
bmMS.mapFrameName = "Map Frame"
bmMS.startingPageNumber = 1
bmMS.currentPageID = 0
bmMS.extentOptions = "BestFit"
bmMS.marginType = "Percent"
bmMS.pages = pageList                   

#Set map series to layout and set the layout CIM definition
lyt_cim.mapSeries = bmMS                
lyt.setDefinition(lyt_cim)              

#Force a refresh of the layout and its associated panes
lyt_cim = lyt.getDefinition('V2')
lyt.setDefinition(lyt_cim)

示例 4:多个相关类 - 在布局上创建面元素

嵌套相关对象的数量可能会变得非常复杂,具体取决于您要尝试创建的对象。 如果可能,我们始终建议您在尝试使用 CIM 创建对象之前先使用托管 API。 接下来的代码示例就是一个完美的典型情况。 您将看到在布局上创建像面元素一样简单的内容将具有许多对象依赖项。 同样,最简捷的方法就是使用单个面元素来创建简单布局,然后将布局导出到 .pagx 文件并查看 JSON 结构。 还有一种方法可以有效处理这些更为复杂的情况,那就是按照相反顺序来构建对象。 先从最缩进的相关子类开始,然后逐步处理到最后生成的对象。 下面的示例代码将使用该模式。

以下代码最终将在布局上创建面 CIMGraphicElement。 该代码将针对构造面图形元素所需的所有相关 CIM 类多次使用 CreateCIMObjectFromClassName

# A simplified JSON structure outlining the objects needed to be generated for
# creating a polygon graphic element on a layout.
#
# CIMGraphicElement
#   CIMPolygonGraphic
#     CIMSymbolReference
#       CIMPolygonSymbol
#         CIMSolidStroke
#           CIMRGBColor
#         CIMSolidFill
#           CIMRGBColor

#Reference layout and its CIM definition
p = arcpy.mp.ArcGISProject('current')
lyt = p.listLayouts()[0]
lyt_cim = lyt.getDefinition('V2')       

#CIMSolidStoke/CIMRGBColor 
strokeRGBColor = arcpy.cim.CreateCIMObjectFromClassName('CIMRGBColor', 'V2')
strokeRGBColor.values = [0, 0, 0, 100]

symLyr1 = arcpy.cim.CreateCIMObjectFromClassName('CIMSolidStroke', 'V2')
symLyr1.capStyle = "Round"
symLyr1.joinStyle = "Round"
symLyr1.width = 1
symLyr1.color = strokeRGBColor

#CIMSolidFill/CIMRGBColor
fillRGBColor = arcpy.cim.CreateCIMObjectFromClassName('CIMRGBColor', 'V2')
fillRGBColor.values = [130, 130, 130, 100] 

symLyr2 = arcpy.cim.CreateCIMObjectFromClassName('CIMSolidFill', 'V2')
symLyr2.color = fillRGBColor

#CIMPolygonSymbol
polySym = arcpy.cim.CreateCIMObjectFromClassName('CIMPolygonSymbol', 'V2')
polySym.symbolLayers = [symLyr1, symLyr2]

#CIMSymbolReference
symRef = arcpy.cim.CreateCIMObjectFromClassName('CIMSymbolReference', 'V2')
symRef.symbol = polySym

#CIMPolygonGraphic
polyGraphic = arcpy.cim.CreateCIMObjectFromClassName('CIMPolygonGraphic', 'V2')
polyGraphic.symbol = symRef
polyGraphic.blendingMode = "Alpha"
polyGraphic.placement = "Unspecified"
polyGraphic.polygon =  {"hasZ": True, "rings": [[[5, 6, None], [1, 6, None], [1, 9, None], [5, 9, None], [5, 6, None]]]}

#CIMGraphicElement
graphicElm = arcpy.cim.CreateCIMObjectFromClassName('CIMGraphicElement', 'V2')
graphicElm.anchor = "BottomLeftCorner"
graphicElm.name = "New Rectangle Graphic"
graphicElm.visible = True
graphicElm.rotationCenter = {"x" : 1, "y": 6}
graphicElm.graphic = polyGraphic

#Add element to EMPTY layout element list and set CIM definition
lyt_cim.elements = [graphicElm]
lyt.setDefinition(lyt_cim)

其他资源和示例脚本

有关详细的 CIM 规范和 GIT 存储库,请参阅制图信息模型 (cim-spec)

有关以各种方式使用 Python CIM 访问的 30 个打包示例脚本集合,请参阅 ArcGIS Pro Python CIM 示例

Python CIM 访问对于更新数据源工作流可能也很有用。 有关更多的 CIM 示例,请参阅更新和修复数据源帮助主题。