使用 Python 自动化地理处理工作流

打开工程和查看数据集

在开始使用 Python 运行地理处理工具之前,您将在 ArcGIS Pro 中下载并查看数据集。

  1. 下载本课程的数据,并将内容提取到您的计算机上的某个位置。

    .zip 文件包含名为 PythonWorkflow 的文件夹。

    在本课程中,数据将显示在 C:\Lessons\PythonWorkflow\ 下。 您可以使用其他文件夹,但如果这样做,则必须在随后的说明和代码中调整路径。

  2. C:\Lessons\PythonWorkflow\ 文件夹中,双击 Workflow.aprx

    Workflow 工程将在 ArcGIS Pro 中打开。

  3. 如果目录窗格尚未显示,请单击视图选项卡,然后单击目录窗格
  4. 目录窗格中,展开文件夹,然后展开 PythonWorkflow
  5. 展开 Transportation.gdb

    Transportation 地理数据库展开以显示要素类。

    此地理数据库中的要素类与交通运输相关。 假设您需要根据这些要素类构建网络。 为了实现该目的,这些要素类需要存储在相同的要素数据集中,并且具有相同的坐标系。 当前情况并非如此。

    在本教程中,您将使用 Python 代码检查要素类的坐标系,并使用投影工具对所有当前不在正确坐标系中的数据集进行转换,从而将其复制到新地理数据库和要素数据集。 您可以通过此操作创建一个网络,但您在本课程中不会构建网络。

    在处理 Python 代码之前,您将检查所选数据集的坐标系并手动运行投影工具。 您将通过此操作了解使用 Python 代码自动化过程所需的信息。

  6. 右键单击 bike_racks,然后单击添加至当前地图

    右键单击 bike_racks 要素类,然后将其添加到当前地图。

  7. 使用相同方法将道路要素类添加到地图。

    这些要素类表示华盛顿特区内的自行车停放架和道路。

    接下来,您将查看两个要素类的坐标系。

  8. 内容窗格中右键单击地图,然后单击属性

    打开地图的“属性”窗格。

  9. 地图属性:地图窗口中,单击坐标系

    单击坐标系。

  10. 展开图层,然后展开 WGS 1984NAD 1983 StatePlane Maryland FIPS 1900 (US Feet) 坐标系的条目。

    展开两个坐标系条目。

    bike_racks 要素类位于名为 WGS 1984 的地理坐标系中,而 roads 和 boundary 要素类位于经过投影的美国国家平面坐标系(马里兰州)NAD 1983 StatePlane Maryland FIPS 1900 (US Feet) 中。

    您的目标是将所有要素类置于具有投影坐标系的数据集中。

  11. 单击确定关闭地图属性窗口。

    您已对地理数据库进行检查,并确定了要素类使用的两个坐标系。 接下来,您将投影其中一个要素类。

投影要素类

接下来,您将投影其中一个要素类并检查工具所需的参数。

  1. 单击功能区中的分析,然后单击地理处理部分中的工具

    单击“分析”,然后在“地理处理”部分中单击“工具”。

    将出现地理处理窗格。

  2. 地理处理窗格中的搜索框内单击,然后输入投影
  3. 在搜索结果中,单击投影(数据管理工具)
  4. 投影工具窗格中,对于输入数据集或要素类参数,请选择 bike_racks
  5. 对于输出数据集或要素类名称,单击浏览按钮并浏览至 Transportation 地理数据库。 展开地理数据库,然后在名称框中输入 bike_racks_sp。 单击保存
  6. 对于输出坐标系,单击下拉列表,然后单击 roads

    “投影”工具的参数已设置完成。

    选择 roads 会将输出坐标系的值设置为 roads 要素类的坐标系,State Plane Maryland 坐标系。

    地理变换参数已设置为 WGS_1984_(ITRF00) To_NAD_1983,因为输入和输出的地理坐标系不同。

    注:

    当输入要素类和输出要素类的地理坐标系不同时,必须使用地理变换。 当地理坐标系相同时,此参数不会显示值列表。 当有必要进行变换时,将显示一个基于输入和输出地理坐标系的下拉列表,并会选择一个默认变换。 在本课程中,您将使用此默认变换。

  7. 单击运行

    投影工具随即运行,已投影的要素类将添加到活动地图。

    为了准备要在网络中使用的数据,您需要对地理数据库中的每个要素类重复此过程:检查坐标系,并决定是否需要运行投影工具。 投影必须进行投影的要素类。 在不进行投影的情况下复制其他要素类。

    您不会手动重复这些步骤,而会改为使用 Python 代码自动化此过程。

  8. 关闭投影工具。
  9. 目录窗格中,右键单击 bike_racks_sp 要素类,单击删除,然后单击永久删除该要素类。

    现在,您即可使用 Python 代码开始工作流。

使用 Python 描述要素类

工作流中的第一步是检查要素类的坐标系。 为执行此操作,您将在 Python 窗口中使用 Python 代码。

  1. 在功能区上,单击分析,然后在地理处理部分中单击 Python 按钮上的下拉箭头,然后单击 Python 窗口

    打开 Python 窗口。

  2. 单击 Python 窗口底部的提示符部分,输入以下代码,然后按 Enter 键。

    desc = arcpy.da.Describe("bike_racks")

    添加用于描述 bike_racks 要素类的代码。

    当您按 Enter 键时,代码将立即运行。 代码不会打印任何信息,但是会创建一个名为 desc 的变量,并将其设置为等于对 bike_racks 要素类运行 Describe 函数的结果。

    Describe 函数会返回一个包含数据集属性的字典。 您可以使用此字典访问空间参考及其他属性。

  3. 在提示符部分中,添加以下代码并按 Enter 键。

    sr = desc["spatialReference"]

    此操作将名为 sr 的新变量设置为数据集属性字典的 SpatialReference 键中存储的值。 SpatialReference 对象包含数据集坐标系的所有相关信息。 您可通过它检查特定属性。

  4. 在提示符部分中,添加以下代码并按 Enter 键。

    print(sr.name)

    此操作会打印空间参考对象的名称。

    打印空间参考对象的名称。

    这样依次检查每个要素类的坐标系有点麻烦,所以您将使用一个 list 函数创建一个列表,以便处理所有的要素类。

创建要素类列表并描述要素类

您可以加速检查要素类坐标系的过程,方法是创建一个要素类列表,然后在 Python 中使用循环结构处理列表并描述每个要素类。

  1. 在提示符部分中,添加以下代码并按 Enter 键。

    fcs = arcpy.ListFeatureClasses()

    此操作将创建一个名为 fcs 的变量,并将其设置为等于对当前工作空间运行 ListFeatureClasses 函数的结果。 您尚未以显式方式设置工作空间,但是 Transportation.gdb 是此工程的默认工作空间。 此函数会返回 Transportation.gdb 中要素类的列表。

  2. 在提示符部分中,添加以下代码并按 Enter 键。

    print(fcs)

    结果是要素类名称的 Python 列表。 列表使用方括号括起来,而要素类名称为 Python 字符串,使用逗号分隔。

    ['bus_lines', 'boundary', 'street_lights', 'roads', 'traffic_analysis_zones', 'bike_routes', 'bike_racks', 'parking_zones', 'intersections', 'station_entrances']

    接下来,您将使用 for 循环处理列表中的每个项目。

  3. 在提示符部分中,添加以下代码:

    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        print(f"{fc}: {sr.name}")

    用于处理要素类列表的 for 循环

    第一行用于定义一个 for 循环。 此代码用于创建一个名为 fc 的临时变量,代码会为此变量分配 fcs 列表中每个要素类的名称。 此代码行以冒号结尾,表示后续内容是要对列表中每个项目运行的代码块。 接下来的三行缩进了四个空格,表示它们属于该代码块。 代码块中的第一行用于创建一个名为 desc 的变量,并将其设置为等于对存储在 fc 变量中的当前要素类值运行 Describe 函数的结果。 第二行用于创建 sr 变量,并将其设置为 desc 中存储的 spatialReference 对象。 第三行将打印一个格式化字符串,其中包含要素类名称、一个冒号和空间参考名称。

    此代码块中的代码用于重复您之前为获取 bike_racks 要素类的空间参考名称所执行的操作过程,但此代码块针对一个变量执行,该变量被设置为列表中的每个项目,因此代码块会处理并报告所有要素类的结果。

  4. 按两次 Enter 键以运行 for 循环及其代码块。

    报告列表中每个要素类的空间参考。

    这些要素类中有一半在一个坐标系中,另一半在另一个坐标系中。

    下一步是编写代码以创建地理数据库并使用投影复制要素工具将要素类加入具有通用投影坐标系的同一数据集中。 您将导出到目前为止所做的工作并将其用作脚本的基础。

创建脚本

接下来,您将继续编写代码以将此过程自动化为脚本。 您可以在 Python 窗口中测试代码,但是对于较长的脚本,通常在 Python 编辑器中编写效果更好。 您将导出到目前为止完成的代码,并在默认的 Python 编辑器 IDLE 中继续处理代码。

  1. 右键单击 Python 窗口脚本部分中的代码,然后单击保存脚本

    右键单击 Python 窗口并保存脚本。

  2. 保存脚本窗口中,浏览至您曾用于提取数据的 PythonWorkflow 文件夹,将脚本命名为 workflow_project.py,然后单击保存

    此操作会将脚本另存为可以在 Python 编辑器中打开的 Python 脚本文件。

  3. 启动 Microsoft File Explorer,然后转至 PythonWorkflow 文件夹。
  4. 右键单击 workflow_project.py,然后单击使用 IDLE 编辑 (ArcGIS Pro)

    右键单击 workflow_project.py 脚本,然后单击“使用 IDLE 编辑 (ArcGIS Pro)”。

    注:
    如果您已安装 ArcGIS Desktop 10.x (ArcMap),则快捷菜单中还将包含快捷选项使用 IDLE 编辑。 请勿使用此快捷选项,因为此选项不会打开正确版本的 Python

    注:
    如果使用 IDLE 编辑(ArcGIS Pro)在快捷菜单中不可见,单击开始,展开 ArcGIS,然后单击 Python 命令提示符。 在 Python 命令提示符窗口中,输入 idle 并按 Enter 键。 IDLE (Python 3.9 Shell) 窗口随即显示。 单击文件,然后单击打开。 浏览至 workflow_project.py 文件并将其打开。

    脚本将在 Python 默认编辑器 IDLE 中打开。 该脚本包括 Python 窗口脚本部分中的所有代码,包括所有已打印的消息,这些消息显示为行首带有井号字符的注释。

    脚本将在 IDLE Python 编辑器中打开。

  5. 在 IDLE 编辑器窗口中,移除 fcs = arcpy.ListFeatureClasses() 行之前的所有代码。
  6. 移除所有注释行。
  7. 移除 print(fcs) 行。

    以下是剩余的代码:

    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        print(f"{fc}: {sr.name}")

    接下来,您将添加用于导入两个库的代码行、设置一些变量以及设置工作空间。

  8. fcs = arcpy.ListFeatureClasses() 行之前添加一个新行,并在脚本的开头添加以下行。

    import arcpy
    import os

    第一行代码用于导入 ArcPy 包以确保在 ArcGIS Pro 外部运行脚本时可以使用 ArcPy 的功能。 第二行用于导入 os 模块,用于处理文件路径。

  9. 在前两行代码后添加一个新行,并添加以下代码行:
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    arcpy.env.workspace = os.path.join(mypath, gdb)

    第一行用于指定数据的位置。 如果您已将 PythonWorkflow 文件夹提取至其他位置,则必须将此行编辑为您计算机上的相应路径。 此值会赋给一个名为 mypath 的变量。 此变量将用于设置工作空间和执行其他任务,例如创建文件地理数据库。

    路径中使用单个正斜线 (/) 而非单个反斜线 (\)。 Python 中的单个反斜杠用作转义字符,可能会产生意想不到的后果。 如果不使用单个正斜线,您也可以在字符串前面使用表示原始 (raw) 的字母 r(例如 r"C:\Lessons\PythonWorkflow"),或使用双反斜线(例如 "C:\\Lessons\\PythonWorkflow")。 所有三种注记均被视为正确注记,可以互换使用。

    下一行将变量 gdb 设置为等于存储感兴趣要素类的地理数据库的名称。

    最后一行通过将数据所在的文件夹 (mypath) 与地理数据库的名称 (gdb) 组合来设置工作空间。 os.path.join() 函数用于将这两个字符串组合为工作空间路径的新字符串。 建议您使用 os.path.join() 执行此操作,因为它可以创建可靠的路径字符串,而不使用单个反斜线 (\)。 这些反斜线会被 Python 读取为转移字符,进而导致错误。

    以下是到目前为止的完整脚本:

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        print(f"{fc}: {sr.name}")

    第一个测试点的脚本

    现在,即可测试您的脚本以确认其可以运行。

  10. 单击文件,然后单击保存

    此操作将保存您对脚本做出的更改。 您也可以在 IDLE 中使用键盘快捷键 Ctrl+S 保存您的工作成果。

  11. 单击运行,然后单击运行模块

    用于运行脚本代码的“运行模块”

    此操作会运行脚本。 您也可以使用键盘快捷键 F5 运行脚本。

    IDLE Shell 窗口随即显示,ArcPy 模块导入时会暂停片刻,之后将打印要素类名称和空间参考。

    首次测试的结果,打印的要素类名称和空间参考

    要完成脚本以自动执行此工作流,您需要添加以下功能:1) 创建一个地理数据库;2) 创建一个要素数据集;3) 复制已经投影的要素类;4) 投影地理坐标系中的要素类。 您将编写每个元素的代码,测试代码,然后继续处理下一个元素。

使用代码创建地理数据库

下一步是将代码添加到脚本以创建地理数据库。 由于您可能需要多次测试脚本,所以需要能够覆盖之前创建的数据。 您将为脚本添加环境设置以支持此需求。

  1. 在以 arcpy.env.workspace 为开头的行后,添加一个新行并添加以下代码:

    arcpy.env.overwriteOutput = True

    接下来,您将创建变量以存储新地理数据库和新要素数据集的名称。

  2. gdb = "Transportation.gdb" 行后,添加一行并添加以下代码:

    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"

    使用变量后,您不再需要在脚本的其余部分重复名称。 这可以增强代码的可重用性。 如果您想为地理数据库或数据集使用其他名称,仅需在脚本中的一个位置更改名称。

    接下来,添加代码以创建地理数据库。

  3. 在以 arcpy.env.overwriteOutput 为开头的行后,添加以下代码:

    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)

    此代码行会调用“创建文件地理数据库”工具。 在括号中,您指定了第一个必填参数(新地理数据库的位置)设置为变量 mypath,其中包含您设置的路径值。 在逗号之后,您提供了工具的另一个必填参数,文件地理数据库的名称。 变量 new_gdb 包含新地理数据库的名称。

    该代码行还会将创建地理数据库的结果赋值给一个变量。 变量 new_gdb_path 包含路径及新创建的地理数据库的名称。 这样更便于在脚本中引用这一新地理数据库。

    测试脚本之前,您将注释掉一些不需要测试的代码。

  4. 选择 new_gdb_path 行之后的所有代码行。

    选择不需要测试的行。

  5. 单击格式,然后单击注释掉区域

    注释掉代码行。

    此操作会将两个井号字符添加到每个所选代码行的开头。 Python 会将以井号开头的行解释为注释,因此它们不会运行。 您可以删除这些行,但是其中的一些代码需要再次使用。 通过注释掉这些代码行,您可以将代码保留在脚本中供后续使用,但当前不运行代码。

    已注释掉一些代码行。

    以下为到目前为止的代码:

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    ##fcs = arcpy.ListFeatureClasses()
    ##for fc in fcs:
    ##    desc = arcpy.da.Describe(fc)
    ##    sr = desc["spatialReference"]
    ##    print(f"{fc}: {sr.name}")

  6. 保存并运行脚本。

    IDLE Shell 窗口重新启动,片刻之后,返回输入提示符 >>>。 该代码目前没有任何可将信息打印到 shell 的生效行,因此难以判断该代码是否有效。 您将在 ArcGIS Pro 中进行检查。

  7. ArcGIS Pro目录窗格的文件夹部分中,右键单击 PythonWorkflow 文件夹,然后单击刷新

    刷新“目录”窗格中的 PythonWorkflow 文件夹。

  8. 展开 PythonWorkflow 文件夹。

    新地理数据库位于文件夹中。

    新地理数据库位于文件夹中。 当前仪表盘为空。

  9. 右键单击 Metro_Transport.gdb,单击删除,然后单击以永久删除该地理数据库。

    在测试脚本时,删除输出通常十分有用,这样做可以轻松地看到脚本是否有效。

    可以使用另一种指示方式表明脚本有效,即添加消息以声明执行了什么操作。 您可以向代码添加 print 语句,以帮助您追踪正在执行的操作。

  10. 在 IDLE 编辑器窗口中以 new_gdb_path = arcpy.CreateFileGDB 为开头的行后,添加一个新行并添加以下代码:

    print(f"The geodatabase {new_gdb} has been created.")

    添加一个用于打印格式化字符串的代码行以表示已创建地理数据库。

    此打印语句会打印一个包含 new_gdb 变量值的格式化字符串。 打印语句不是脚本运行所必需的,但它们可以帮助您跟踪脚本正在执行的操作。 它们也十分有助于排除长脚本中的错误。 您可以在脚本的不同位置添加多个指示状态的打印语句,当您看到各消息时,便可得知脚本已经执行到该位置。 您也可以使用格式化字符串打印脚本中的变量值;此方法十分有助于排除错误。

  11. 保存脚本。

使用代码创建要素数据集

接下来,您将在新地理数据库中创建要素数据集。 要素数据集的一个最典型的属性是要素数据集中的所有要素类共享相同的坐标系。

您将为此数据集使用 State Plane Maryland 坐标系。 虽然在 Python 中设置坐标系时可以使用坐标系名称,但是使用被称为 WKID 或熟知标识符的短代码更加简单。

  1. ArcGIS Pro 中的内容窗格中,右键单击 roads 图层,然后单击属性
  2. 图层属性窗格中,单击选项卡。

    单击“图层属性”窗格的“源”选项卡。

  3. 单击数据源以折叠数据源部分。

    折叠“数据源”部分。

  4. 单击空间参考将其展开。

    单击“空间参考”以展开“空间参考”部分。

    此坐标系的 WKID 代码为 2248。

    WKID 代码为 2248。

  5. 单击取消以关闭图层属性窗格。

    现在,您将使用此 WKID 代码设置要素数据集的空间参考。

  6. 在 IDLE 中以 print(f"The geodatabase 为开头的行后,添加以下代码:

    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")

    用于创建要素数据集并打印数据集创建报告的代码行。

    第一行用于运行创建要素数据集工具,为其提供了三个必填参数。 第一个参数是要创建要素数据集的地理数据库位置,第二个是要素数据集的名称,第三个是数据集坐标系的 WKID。 new_gdb_path 变量包含数据库的完整路径。 要素数据集的名称之前已赋给 fds 变量。

    另一种设置坐标系的方法是提供现有要素类的路径,例如,提供 Transportation.gdb 地理数据库中 roads 要素类的路径。

    第二行用于打印一个格式化字符串,用于表示新数据集已创建。

    以下为完整代码:

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    ##fcs = arcpy.ListFeatureClasses()
    ##for fc in fcs:
    ##    desc = arcpy.da.Describe(fc)
    ##    sr = desc["spatialReference"]
    ##    print(f"{fc}: {sr.name}")

  7. 保存并运行代码。

    代码随即运行,片刻之后,两个状态消息将打印至 IDLE shell。

    代码运行并报告状态。

  8. ArcGIS Pro目录窗格中,右键单击 PythonWorkflow 文件夹,然后单击刷新

    Metro_Transport 地理数据库已创建。

  9. 展开 Metro_Transport 地理数据库。

    Metro_Network 数据集已创建。

  10. 删除 Metro_Transport 地理数据库。

使用代码根据条件复制要素类

接下来,您将使用之前注释掉的一部分代码列出 Transportation.gdb 地理数据库中的要素类。 您将向其中添加逻辑以检查每个要素类的空间参考 WKID 是否为 2248,并编写代码以在该条件为真时将要素类复制到新的地理数据库。

  1. 在 IDLE 中,选择之前注释掉的代码行。
  2. 单击格式,然后单击取消注释区域

    取消注释代码。

    取消注释代码会删除每一行之前的井号,因此代码将运行而不是被解释为注释。

    您取消注释的代码可创建当前工作空间中要素类的列表,然后使用列表中各个项目的描述提取空间参考。 现在,您将添加代码以检查空间参考值并选择复制或投影要素类,而不是打印该信息。

    复制要素工具和投影工具都会使用一个输入要素类并生成一个输出要素类。 虽然要素类的名称可以保持相同,但输出的路径将有所不同,因为新的要素类将位于新的地理数据库中。

    输入要素类通过变量 fc 表示。 fc 的值是从当前工作空间的要素类列表派生的要素类名称。

    例如,其中一个输入要素类的完整路径为:C:\Lessons\PythonWorkflow\Transportation.gdb\roads

    因为已经设置了工作空间,所以在工具中可以直接使用要素类的名称(例如 roads)。 当使用当前工作空间中的要素类时,不需要完整路径。 这就是 desc = arcpy.da.Describe(fc)desc = arcpy.da.Describe("roads") 有效的原因。

    但是,您必须为输出要素类参数提供新工作空间中的新要素类的完整路径。 与之前在脚本中设置环境时类似,可以使用 os.path.join() 构建此路径。

  3. 选择以 print(f"{fc}: 为开头的代码行,然后使用以下代码行将其替换:

    new_fc = os.path.join(mypath, new_gdb, fds, fc)

    此代码应该具有相同的缩进级别,位于 for fc in fcs: 循环代码块中。

    在此代码行中,新变量 new_fc 被设置为等于将数据所在的文件夹 (mypath)、新地理数据库 (new_gdb) 和新要素数据集 (fds) 连接到一起所创建的路径。 路径的最后一部分是新要素类的名称,该名称与输入要素类相同(变量 fc 的值)。 路径的这一部分随着要素类列表循环的每一次迭代而改变。

    创建输出要素类的完整路径后,您就可以添加代码以根据坐标系决定是复制还是投影各个要素类。 在 Python 中,您可以使用 if 语句测试不同的条件,然后根据语句中的条件是否为真运行不同的代码块。

  4. new_fc = os.path.join 行之后的相同缩放级别处(for 循环内部),添加以下代码行:

    if sr.factoryCode == 2248:

    此代码用于检查要素类的 WKID(存储在 sr 对象中作为其 factoryCode 值)是否与 State Plane Maryland 坐标系的 WKID 2248 相匹配。

    此代码使用 if 语句和一个表达式,并使用冒号结尾以指示后面跟随的是语句为真时将会运行的代码块。

    该语句使用双等号。 在 Python 中,单个等号用于将变量设置为某个值,而双等号用于检查是否相等。

  5. 单击该代码行的末尾,然后按 Enter 键。

    此操作使下一行代码具有正确的缩进,即相对于 if 语句行缩进四个空格。 这是新代码块的开始,此代码块仅会在 sr.factoryCode 等于值 2248 时运行。

    创建输出要素类的完整路径并且满足对坐标系的测试后,您可以添加代码以复制要素类。

  6. 在新缩进的行处,添加以下代码行:

    arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")

    第一行用于运行“复制要素”工具,将当前要素类复制到新的地理数据库。

    第二行用于打印一个格式化字符串,用于表示新数据集已创建。

    以下为完整代码:

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        new_fc = os.path.join(mypath, new_gdb, fds, fc)
        if sr.factoryCode == 2248:
            arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")

    用于在 WKID 为 2248 时在地理数据库之间复制要素类的逻辑已添加到脚本

  7. 保存并运行代码。

    已复制匹配的要素类。

    该代码随即运行。 代码会创建地理数据库和要素数据集,并会复制位于 State Plane Maryland 坐标系中的五个图层。

  8. ArcGIS Pro 中的目录窗格中,刷新 PythonWorkflow 文件夹。
  9. 刷新 Metro_Transport 地理数据库并将其展开。
  10. 刷新 Metro_Network 要素数据集并将其展开。

    五个要素类已复制到新地理数据库。

    地理数据库和数据集包含与数据集坐标系匹配的要素类。

添加代码以根据条件投影要素类

完成脚本的最后一步是添加逻辑以使用“投影”工具投影不在 State Plane Maryland 坐标系中的要素类,并将结果写入新地理数据库中的要素数据集。

  1. 在 IDLE 中以 print(f"The feature class 为开头的代码行末尾单击,然后按 Enter 键。
  2. Backspace 键以减少一个级别的缩进。

    您将添加一个 else 语句,此语句必须与之前的 if 语句位于同一缩进级别。

    else 语句用于在 if 语句为假时运行一个不同的代码块。

  3. 在减少缩进的新行处,添加以下代码行:

    else:
            arcpy.Project_management(fc, new_fc, 2248)
            print(f"The feature class {fc} has been projected.")

    if 语句和 else 语句位于同一缩进级别。

    else 语句用于创建一个包含代码块的逻辑分支,检查 if 语句后,如果结果不为真,则将运行该代码块。 该逻辑为:如果 WKID 是 2248,则复制要素类,否则,将投影要素类。

    这些代码行中的第二行缩进了四个空格,表示其属于在 else 条件下运行的代码块。 投影工具会将输入要素类投影到 State Plane Maryland 坐标系,并且输出要素类将存储在新地理数据库中。 投影工具的参数为输入要素类、输出要素类和输出坐标系(此参数使用 WKID 2248)。

    注:
    投影工具存在第四个参数,该参数为可选变换。 当您之前运行投影工具时,您看到需要在 NAD 1983 地理坐标系和 WGS 1984 地理坐标系之间进行变换,但默认情况下,系统会在运行该工具时选择适当的变换。 这意味着无需在此处的代码中指定变换。

    基于之前得出的所有要素类坐标系的检查结果,您了解到当前不在 State Plane Maryland 坐标系中的要素类位于一个特定的地理坐标系中。 但是,无需指定此特定的坐标系。 通过使用 else 语句,将对所有 if 语句为假的要素类运行投影工具,无论特定的坐标系是什么。

    以下为完整代码:

    import arcpy
    import os
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        new_fc = os.path.join(mypath, new_gdb, fds, fc)
        if sr.factoryCode == 2248:
            arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")
        else:
            arcpy.Project_management(fc, new_fc, 2248)
            print(f"The feature class {fc} has been projected.")

    脚本的完整代码

  4. 保存并运行脚本。

    该代码随即运行。 代码会创建地理数据库和要素数据集,复制位于 State Plane Maryland 坐标系中的五个图层,并投影 WGS84 坐标系中的五个图层。

    最终的代码运行结果

  5. ArcGIS Pro目录窗格中,刷新 Metro_Network 要素数据集。

    数据集包含所有要素类,这些要素类均位于正确的坐标系。

    包含所有要素类的最终地理数据库

    您的代码运行正常,此时,您将可以创建几何网络。

为脚本添加注释

这是一个相对简单的脚本,但建议您在代码中添加注释以使其更易于理解。 注释可用于解释脚本用途和标识关键步骤。 这样可以使其他用户更容易理解您的脚本,并根据其目的修改脚本。 如果您在长时间不使用脚本后需要继续修改脚本,注释有助于您理解代码。

注释以一个或多个井号字符为开头。 可以将注释置于代码行的开头,也可以将其添加到代码行的末尾。

  1. 在 IDLE 中,在脚本的开头添加一个新行。
  2. 将以下注释复制并粘贴到新行中:

    # Author: your name
    # Date: the date
    # Purpose: This script reads all the feature classes in a
    # geodatabase and copies them to a new feature dataset in
    # a new geodatabase. Feature classes not already in the
    # target coordinate system are projected.

  3. 编辑 AuthorDate 行以添加您的姓名和当前日期。
  4. import arcpy 行之前,添加两个新行,并在第二行添加以下注释:

    # Imports

    空白行不会影响代码,但可以使代码更加清晰。 注释标明此部分用于导入代码所需的库。 导入语句通常集中放置在脚本顶部附近。

  5. import os 行之后添加两个新行并添加以下注释:

    # Variables for paths, outputs, workspaces

    此注释标明首次设置这些变量的位置。

  6. arcpy.env.overwriteOutput = True 行之后添加两个新行并添加以下注释:

    # Create a new geodatabase and dataset

  7. fcs = arcpy.ListFeatureClasses() 行之前添加两个新行并添加以下注释:

    # Create a list of feature classes in the workspace

  8. if sr.factoryCode == 2248: 行之后,在同一行添加以下注释:

     # WKID of target coordinate system

    您已添加用于解释代码的注释。

    以下为完整代码:

    # Author: your name
    # Date: the date
    # Purpose: This script reads all the feature classes in a
    # geodatabase and copies them to a new feature dataset in
    # a new geodatabase. Feature classes not already in the
    # target coordinate system are projected.
    
    # Imports
    import arcpy
    import os
    
    # Variables for paths, outputs, workspaces
    mypath = "C:/Lessons/PythonWorkflow"
    gdb = "Transportation.gdb"
    new_gdb = "Metro_Transport.gdb"
    fds = "Metro_Network"
    arcpy.env.workspace = os.path.join(mypath, gdb)
    arcpy.env.overwriteOutput = True
    
    # Create a new geodatabase and dataset
    new_gdb_path = arcpy.CreateFileGDB_management(mypath, new_gdb)
    print(f"The geodatabase {new_gdb} has been created.")
    arcpy.CreateFeatureDataset_management(new_gdb_path, fds, 2248)
    print(f"The feature dataset {fds} has been created.")
    
    # Create a list of feature classes in the workspace
    fcs = arcpy.ListFeatureClasses()
    for fc in fcs:
        desc = arcpy.da.Describe(fc)
        sr = desc["spatialReference"]
        new_fc = os.path.join(mypath, new_gdb, fds, fc)
        if sr.factoryCode == 2248: # WKID of target coordinate system
            arcpy.CopyFeatures_management(fc, new_fc)
            print(f"The feature class {fc} has been copied.")
        else:
            arcpy.Project_management(fc, new_fc, 2248)
            print(f"The feature class {fc} has been projected.")

    包含注释的最终代码

  9. 保存脚本。

在本教程中,您学习了以下内容:

  • Python 脚本可用于自动化 GIS 工作流中的重复性任务。
  • ArcPy 包含多个用于创建数据集列表的函数。
  • 通过使用 Python 代码列出和描述数据集,您可以在工作空间中创建详细的 GIS 数据集清单。 然后,您可以决定根据其特征以不同方式处理每个数据集。
  • 要确保正确输出,必须谨慎处理路径和文件名。

您也可能对由 Esri Press 出版的 Paul A.Zandbergen 博士的适用于 ArcGIS ProPython 脚本适用于 ArcGIS Pro 的高级 Python 脚本感兴趣。