针对最新数据制图

珊瑚依靠藻类生存。海洋温度过冷或过热都会使藻类减少,使珊瑚白化并增加死亡率。NOAA 珊瑚礁观测计划提供关于珊瑚白化风险的全球数据。此数据经常更新。

在本课程中,您将使用 ArcGIS Pro 和 Python 将最新的珊瑚白化数据检索为 JSON 文件。然后,您将基于数据创建两个要素类、更改其符号系统并进行发布。在后续课程中,您将开发源例程,以便在新数据可用时自动更新这些图层和服务。

导入 ArcPy 和 ArcGIS API for Python

首先,您将在 ArcGIS Pro 中创建新工程并更改其底图。然后,您将使用 Python 来导入 ArcPy 和 ArcGIS API for Python.

ArcPy 是一个 Python 站点包。通过它,您可以使用 Python 来运行地理处理工具及其他 ArcGIS 功能。ArcGIS API for Python 是一个 Python 库,也可以支持 Python 执行 GIS 任务。稍后,您将使用它来连接到 ArcGIS OnlineArcGIS Enterprise

  1. 启动 ArcGIS Pro。如果出现提示,请使用您获得许可的 ArcGIS 帐户(或 ArcGIS Enterprise 门户指定用户帐户)进行登录。
    注:

    如果您没有 ArcGIS Pro,可以注册 ArcGIS 免费试用版。如果您要登录 Enterprise 帐户,请确保将 ArcGIS Pro 配置为使用您组织的门户。

  2. 空白模板下,单击地图

    地图模板

  3. 新建工程窗口中,对于名称,输入 Coral Bleaching。单击确定

    随即在 ArcGIS Pro 中打开一个空白地图工程。根据您组织的设置,默认范围可能有所不同。首先,您需要更改底图,使其突出显示您的数据。

  4. 单击功能区上的地图选项卡。在图层组中,单击底图并选择浅灰色画布

    “浅灰色画布”底图选项

    底图随即添加到地图和内容窗格中。底图还包括一个包含地名的参考图层。您不需要此参考图层,因此需将其关闭。

  5. 内容窗格中,取消选中 World Dark Gray Reference 图层。

    “内容”窗格中的 World Light Gray Reference 图层将关闭

    接下来,您将打开 Python 窗口。

    ArcGIS Pro 通过 Anaconda Distribution 附带 Python 3。Anaconda Distribution 包括多个用于数据科学应用的常见 Python 模块。

  6. 在功能区上,单击分析选项卡。在地理处理组中,单击 Python

    “分析”选项卡上的 Python 按钮

    随即显示 Python 窗口。窗口包含两个部分,Python 提示符和脚本。Python 提示符是您输入 Python 代码的地方。脚本提供您所输入的 Python 代码的记录。

    首先,您将运行一行简单的 Python 代码,以熟悉基本的 Python 语法。

    提示:

    您可以按您喜欢的方式重新定位 Python 窗口并调整其大小。拖动标题栏以重新定位窗格,拖动窗格边缘以调整大小。您也可以将其停靠在 ArcGIS Pro 中的多个区域。

  7. 单击 Python 提示符,(其中显示在此处输入 Python 代码),输入 print('Hello World!') 然后按 Enter 键。

    包含打印函数的脚本

    print() 函数使脚本显示括号中的文本。在本例中,print() 是函数,而 'Hello World!' 是参数(函数的变量或输入)。

    通过输入函数名称并在括号中加入参数,您可以执行多种 Python 函数。但是,并非所有 Python 函数都需要参数,而其中一些函数还会需要多个参数(以逗号分隔)。

    函数将在脚本中返回值。另一方面,语句将执行进程而不返回值。要导入模块(例如 ArcPy),您将使用语句而不是函数。首先,您将导入 sys 模块。此模块提供特定于您的系统的多个函数。

  8. 在 Python 提示符中,输入 import sys 并按 Enter 键。

    sys 模块已导入。接下来,您将使用 version 属性显示您的 Python 版本。属性是 Python 对象(函数、变量或常数)的属性。可以使用一个点将其附加至 Python 对象。

  9. 输入 sys.version,然后按 Enter 键。

    包含 import sys 和 sys.version 行的脚本

    在本例中,sys 函数是对象,而 version 是它的属性。

    脚本将返回关于您的 Python 版本的信息。在示例图像中,版本为 3.6.6。根据您的 ArcGIS Pro 版本,Python 版本可能有所不同。

    通过 ArcPy,您可以使用 Python 提示符运行 ArcGIS 地理处理工具。接下来。您将使用导入 sys 模块的方法来导入 arcpy 模块。

  10. 在 Python 提示符中,输入 import arcpy 并按 Enter 键。

    arcpy 模块已导入。

  11. 输入 help(arcpy) 并按 Enter 键。

    包含 import arcpy 和 help(arcpy) 行的脚本

    help() 函数提供关于给定变量 (arcpy) 的信息。在本例中,已添加大量的信息。您可能想要调整 Python 窗口的大小以查看所有内容。

    接下来,您将使用 arcgis 模块导入 ArcGIS API for Python

  12. 在 Python 提示符中,输入 import arcgis 并按 Enter 键。

    已导入 ArcGIS API for Python

    注:

    如果您在导入 arcgis 模块时收到 ModuleNotFoundError 消息,表示在您的 ArcGIS Pro 实例中未安装 ArcGIS API for Python。要进行安装,单击工程选项卡,然后单击 Python 选项卡。单击添加包并搜索 arcgis。在搜索结果列表中,单击 arcgis 包并单击安装安装和设置指南中更详细地介绍了安装 ArcGIS API for Python 的方法。

  13. 输入 help(arcgis) 并按 Enter 键。

    包含 import arcgis 和 help(arcgis) 行的脚本

    随即显示有关于 arcgis 模块的信息。

下载文件

接下来,您将从 NOAA 珊瑚礁观测计划下载 JSON 格式的空间数据。此数据包含珊瑚白化风险的最新数据信息。

数据托管在珊瑚礁观测网站上。要对该数据进行检索,您将使用多个函数。这些函数需要您先导入适当的模块。

  1. 在 Python 提示符中,运行以下行:
    import os, tempfile

    ostempfile 模块已导入。您还将导入 urllib 模块的子模块 request

  2. 运行以下行:
    from urllib import request

    request 子模块包含 urlretrieve 函数,您将使用它来检索数据。urlretrieve 函数需要两个变量:在线文件的 URL (url) 和该文件在您的计算机上保存的位置 (filename)。

    在 Python,使用等号 (=) 可以定义变量和为变量赋值。要定义 filename 变量,您将运行 os.path.join() 函数引入包含所需文件名的临时目录 (temp_dir)。要定义临时目录,您将运行 tempfile.mkdtemp() 函数。

    注:

    filename 变量可以是任意指向您的计算机某个位置的路径。然而,建议将文件保存在临时目录中。使用 os.path.join() 函数是因为它适用于任何操作系统,无论文件路径中使用什么字符来分割文件夹,该函数均可正确运行。

  3. 运行以下行(复制粘贴以一次性运行全部行):
    url = 'https://coralreefwatch.noaa.gov/vs/vs_polygons.json'
    temp_dir = tempfile.mkdtemp()
    filename = os.path.join(temp_dir, 'latest_data.json')
    response = request.urlretrieve(url, filename)

    这些行定义了所有必要的变量。要检查检索的 JSON 文件路径,您需将 filename 作为参数运行 print 函数。

  4. 运行以下行:
    print(filename)

    包含新数据路径的脚本

    在示例图像中,最后一行是您检索的 latest_data.json 文件的路径(您的路径将不同)。您可以复制文件名并粘贴到计算机的文件资源管理器(例如 Windows 资源管理器)以打开文件。可以在任何文本编辑器中打开文件。

    接下来,您将创建 data_raw 变量以使用 JSON 格式来表示数据。每当在代码行中引用 JSON 数据时,您都将使用此变量。要创建变量,您将需要导入 json 模块以运行 json.load() 函数。您还将创建一个名为 json_file 的中间变量,它将打开您的文件。

  5. 运行以下行:
    import json
    json_file = open(filename)
    data_raw = json.load(json_file)

    尽管脚本中什么都没有发生,json_file 变量(您的 JSON 文件)已打开,data_raw 变量随之加载。

    注:

    json_file 变量将保持打开,直到运行 json_file.close() 命令。另一种打开文件的方法是使用 with 语句。执行此语句会在代码块关闭后自动关闭文件。以下几行代码表示了如何通过 with 语句打开 json_file 变量:

    with open(filename) as json_file:
        data_raw = json.load(json_file)    # Do something with the 'data_raw' variable
    # Do something else outside the 'with' section. The json_file variable is now closed.

    以数字符号 (#) 开头的行是注释,不会影响代码运行,并能够为用户提供信息。

从文件创建图层

要可视化您下载的数据(并进一步熟悉如何使用 Python 与空间数据交互),您将基于 JSON 文件创建两个要素类。

首先,您将创建一个文件地理数据里以包含要素类。文件包含点和面要素的数据,因此您需要将其分为两个 JSON 文件,分别用于两个要素类。然后,您将为每个 JSON 文件创建要素类,并将其保存于地理数据库中。

urlretrieve 相似,创建地理数据库的函数 (arcpy.management.CreateFileGDB) 需要路径和名称。您还将运行 arcpy.env.workspace 函数将地理数据库设置为您的默认工作空间。

  1. 在您的计算机的 C 盘上,创建一个名为 Temp 的文件夹。
  2. 在 Python 提示符中,运行以下行:
    arcpy.management.CreateFileGDB(r'C:\Temp', 'Live.gdb')
    arcpy.env.workspace = os.path.join(r'C:\Temp', 'Live.gdb')

    Temp 文件夹中已创建 Live 地理数据库(您可以打开文件夹以进行检查)。接下来,您将创建两个字典,一个用于点要素(观测站),另一个用于面要素(NOAA 确定的感兴趣区域)。

    在 Python 中,字典是无序索引项的集合。根据 GeoJSON 文件格式的要求,您所创建的字典将包含两个元素。type 元素将引用 data_raw 变量(您的 JSON)中的几何类型。features 元素将列出要素。现在,列表是空的,如一对括号所示。

  3. 运行以下行:
    data_stations = dict(type=data_raw['type'], features=[])
    data_areas = dict(type=data_raw['type'], features=[])

    包含用于创建字典的代码行的脚本

    字典已创建。接下来,您需要将 data_raw 变量中的要素加载至 data_stationsdata_areas 字典,具体取决于要素几何类型。

    接下来,您将创建 for 循环。for 循环可为列表中的每一项执行函数或语句。您将创建一个为 data_raw 函数中的所有要素执行的循环。通过创建 if 条件语句,您将确定每个要素的几何类型。然后,您将使用 append() 方法将特定几何类型的要素附加到适当字典的要素列表中。

  4. 运行以下行:
    for feat in data_raw['features']:
        if feat['geometry']['type'] == 'Point':
            data_stations['features'].append(feat)
        else: # elif feat['geometry']['type'] in ['MultiPolygon', 'Polygon']:        
            data_areas['features'].append(feat)
    警告:

    Python Software Foundation 建议使用空格而非制表符来缩进代码行。不要在进行缩进时混合使用制表符和空格,否则您的代码将无法正确运行。

    针对 JSON 数据汇总列出的每个要素,如果其几何类型为点,则要素将附加至 data_stations 字典。如果几何类型是面或多面,要素则会附加至 data_areas 字典。

    您将使用 data_stations['features'] 列表运行 len() 函数,以检查列表中加载了多少要素。

  5. 运行以下行:
    len(data_stations['features'])

    脚本显示用于计数观测站数量的 len() 函数

    该行将返回数值 213,表明有 213 个点要素。JSON 中的面要素对应 NOAA 确定的感兴趣区域。这些区域会定期更改,因此您无法像验证站点一样轻松地验证他们。

    因此,您将访问列表中第十个要素的名称和坐标。在 Python 中,列表以 0 而不是 1 为开头,因此第 10 个要素是要素 9。

  6. 运行以下行:
    data_areas['features'][9]['properties']['name']

    脚本将返回第 10 个要素的名称。

  7. 运行以下行:
    data_areas['features'][9]['geometry']['coordinates']

    脚本将返回一长串坐标,对应面的各个折点。

    注:

    由于此数据会定时更新,您的结果可能与示例图片不同。

    脚本显示比格尔湾要素的名称和坐标

    接下来,您需要将字典作为 JSON 文件保存在您保存原始 JSON (temp_dir) 的临时目录中。您将运行 os.path.join() 函数以创建每个新的 JSON 的文件路径。然后,您将创建 with 语句并使用 json.dump() 函数以将字典另存为 JSON 文件。

  8. 运行以下行(注释为可选):
    # Filenames of temp json files 
    stations_json_path = os.path.join(temp_dir, 'points.json')
    areas_json_path = os.path.join(temp_dir, 'polygons.json')
    # Save dictionaries into json files
    with open(stations_json_path, 'w') as point_json_file:
        json.dump(data_stations, point_json_file, indent=4)
    with open(areas_json_path, 'w') as poly_json_file:
        json.dump(data_areas, poly_json_file, indent=4)

    您将对每个路径运行 print() 函数以确定文件是否正确保存。

  9. 运行以下行:
    print(stations_json_path)
  10. 运行以下行:
    print(areas_json_path)
    注:

    您的文件路径可能与示例图片中显示的有所不同。

    每个 JSON 文件均含有 print() 函数的脚本

    每个路径均转至 Temp 文件夹。文件夹名称为 points.json 和 polygons.json,正如您在运行 os.path.join() 函数时所指定的那样。如果需要,您可以复制每个路径并在任何文本编辑器中打开文件。

    现在,JSON 文件已创建,您将运行 arcpy.conversion.JSONToFeatures() 函数将其转换为要素类。此函数需要 JSON 文件的路径和所要创建的要素类的名称。

  11. 运行以下行:
    # Convert JSON files to features
    arcpy.conversion.JSONToFeatures(stations_json_path, 'alert_stations') 
    arcpy.conversion.JSONToFeatures(areas_json_path, 'alert_areas')

    要素类保存在默认工作空间中,您之前将其指定为 Live 地理数据库。两个图层(alert_stations 和 alert_areas)已添加至地图。

    地图显示观测站和区域

更改符号系统

您也可以使用 Python 来更新图层的符号系统。尽管执行这一操作不需要创建源例程,但是,最好以一种具有视觉吸引力和有意义的方式来显示数据。另外,如果您以后决定更改符号系统,则可以快速调整您创建的用于更改符号系统的代码。

您将基于警报级别符号化图层,根据记录的炎热压力,警报级别处于 0 到 4 之间。较低的警报级别为蓝色,而较高的警报级别为红色。图层包含警报级别的文本字段,但字段必须为数字才能为其提供分级符号系统。

首先,您将使用 arcpy.management.AddField 函数为警报级别创建新的数值字段。对于此函数的参数,首先列出要添加该字段的图层,然后列出字段名称,接下来是字段类型和字段别名。您也可以指定其他设置,但是上述参数是这些字段所需要的。

  1. 在 Python 提示符中,运行以下行:
    # Add alert_level field
    arcpy.management.AddField('alert_stations', 'alert_level', 'SHORT', field_alias='Alert Level')
    arcpy.management.AddField('alert_areas', 'alert_level', 'SHORT', field_alias='Alert Level')

    alert_level 字段同时添加到 alert_stations 和 alert_areas 图层中。字段的数据类型均为短整型(一种数值数据类型),别名为 Alert Level

    接下来,您将使用 arcpy.management.CalculateField 函数来计算新字段。此函数还将图层名称、字段名称以及用于字段的表达式作为参数。您的表达式将使用 int() 函数将 alert 文本字段的值转换为整型。

  2. 运行以下行:
    # Calculate alert_level field
    arcpy.management.CalculateField('alert_stations', 'alert_level', "int(!alert!)")
    arcpy.management.CalculateField('alert_areas', 'alert_level', "int(!alert!)")

    字段已计算。

    提示:

    如果您想想要确认字段是否已正确计算,右键单击 alert_stationsalert_areas 图层并选择 属性表。滚动至表格的末尾以确认 Alert Level 字段已添加,其值介于 0 到 4 之间。

    接下来您将基于新字段更改 alert_stations 图层的符号系统。首先您将创建变量以表示当前工程 (p) 和地图 (m)。您还将为 alert_stations 图层 (points_lyr) 及其符号系统 (points_sym) 创建变量。

  3. 运行以下行:
    # Symbology
    p = arcpy.mp.ArcGISProject("CURRENT")
    m = p.listMaps('Map')[0]
    # Points
    points_lyr = m.listLayers('alert_*')[0]
    points_sym = points_lyr.symbology

    接下来,您将更新渲染器。当前,符号系统使用 SimpleRenderer 类型(单一符号)进行渲染。要基于字段以不同的方式符号化要素,也需要将渲染器更改为 GraduatedSymbolsRenderer(分级符号)。

    您还要将渲染器设置为使用 alert_level 字段作为分类字段并将数据分为 4 类(0 到 1、1 到 2、2 到 3 和 3 到 4)。您将针对每一类设置其大小和颜色,使具有较高警报级别的类的大小增加,颜色从蓝色变为红色。

  4. 运行以下行:
    # Always change to the GraduatedSymbolsRenderer from the SimpleRenderer
    if points_sym.renderer.type != 'SimpleRenderer':
        points_sym.updateRenderer('SimpleRenderer')
    points_sym.updateRenderer('GraduatedSymbolsRenderer')
    points_sym.renderer.classificationField = 'alert_level'
    points_sym.renderer.breakCount = 4
    points_labels = ['0 - 1', '> 1 - 2', '> 2 - 3', '> 3 - 4']
    points_upperBounds = [1, 2, 3, 4]
    points_sizes = [6, 16.50, 27, 37.50] 
    layers_colors = [{'RGB': [5, 113, 176, 40]}, {'RGB': [146, 197, 222, 50]},
                       {'RGB': [244, 165, 130, 50]}, {'RGB': [202, 0, 32, 30]}]

    接下来,您将创建一个 for 循环以将您指定的大小和颜色应用到各个类。您的类包含在 1 到 4 的数字列表中。您将使用 i(表示整型)作为占位符变量以代表用数字表示的类。

  5. 运行以下行:
    for i in range(4):
        item = points_sym.renderer.classBreaks[i]
        item.symbol.applySymbolFromGallery('Circle', 1)
        item.label = points_labels[i]
        item.upperBound = points_upperBounds[i]
        item.symbol.size = points_sizes[i]
        item.symbol.color = layers_colors[i]

    此循环将遍历指定范围 (4) 内的所有整数。对于第一个整数,将使用您之前创建的列表中的第一个标签、上限、大小和颜色。对于第二个整数,将使用第二组值,以此类推至范围结束。

    最后,您将运行一个代码行,从而基于您之前运行的行来更新图层的符号系统。

  6. 运行以下行:
    # Update
    points_lyr.symbology = points_sym

    符号系统随即更新。(由于源数据更新,您的地图可能与示例图像不同。)

    具有更新的点符号系统的地图

    使用类似的代码,您可以更改 alert_areas 图层的符号系统。首先,您将为图层 (polygons_lyr) 及其符号系统 (polygons_sym) 创建变量。

  7. 运行以下行:
    # Polygons
    polygons_lyr = m.listLayers('alert_*')[1]
    polygons_sym = polygons_lyr.symbology

    接下来,您将更新渲染器并创建四个类以便与您为点图层创建的类相匹配。

  8. 运行以下行:
    # Always change to the GraduatedSymbolsRenderer from the SimpleRenderer
    if polygons_sym.renderer.type != 'SimpleRenderer':
        polygons_sym.updateRenderer('SimpleRenderer') 
    polygons_sym.updateRenderer('GraduatedColorsRenderer')
    polygons_sym.renderer.classificationField = 'alert_level'
    polygons_sym.renderer.breakCount = 4
    polygons_labels = ['0 - 1', '> 1 - 2', '> 2 - 3', '> 3 - 4']
    polygons_upperBounds = [1, 2, 3, 4]
    layers_colors = [{'RGB': [5, 113, 176, 40]}, {'RGB': [146, 197, 222, 50]},
                       {'RGB': [244, 165, 130, 50]}, {'RGB': [202, 0, 32, 30]}]

    最后,您将创建用于改变每个类的标签、大小和颜色的循环并更新图层符号系统。

  9. 运行以下行:
    for i in range(4):
        item = polygons_sym.renderer.classBreaks[i]
        item.label = polygons_labels[i]
        item.upperBound = polygons_upperBounds[i]
        item.symbol.color = layers_colors[i]
    # Update
    polygons_lyr.symbology = polygons_sym

    符号系统随即更新。(可能需要放大才能更加清楚地进行查看)。

    具有更新的面符号系统的地图

  10. 保存工程。

发布图层

接下来,您会将图层发布至 ArcGIS OnlineArcGIS Enterprise 门户。

  1. 确认您已经登录至 ArcGIS Online 帐户(或使用指定用户帐户登录 ArcGIS Enterprise 门户)。
    注:

    如果您已登录,则您的帐户名称将显示在 ArcGIS Pro 的右上角。

  2. 单击功能区上的共享选项卡。在共享为组中,单击 Web 图层

    “共享为”组中的“Web 图层”按钮

  3. 共享为 Web 图层窗格中,设置以下参数:
    • 对于名称,输入 Coral Reef Watch
    • 对于摘要,输入 NOAA's latest data for risk of coral bleaching
    • 对于标签,输入 NOAACoral BleachingAlert Levels,并在每个标签之间按 Enter 键。
    • 对于图层类型,请确认选择了要素

    项目详细信息和图层类型参数

  4. 单击分析

    将分析图层以确保不存在会阻止发布的错误。分析返回零错误,以及一些与要素模板和数据源相关的警告。考虑本练习的目的,您可以忽略这些警告。

  5. 单击发布

    该工具随即运行。窗格底部将显示确认 web 图层已发布的消息。

  6. 保存工程。

    接下来,您将通过将图层添加至 web 地图来确认图层已成功发布。

  7. 登录到您的 ArcGIS 组织帐户ArcGIS Enterprise 门户。
  8. 在功能区中,单击内容

    功能区中的内容选项

    两个新项目已添加到您的 内容 页面:Coral Reef Watch 要素图层和服务定义。

  9. 对于 Coral Reef Watch 要素图层,单击选项按钮(三个水平点)并选择在 Map Viewer 中打开

    在地图查看器中打开选项

    包含您所创建的图层的 web 地图随即打开。

在本课程中,您使用了 Python 来检索珊瑚礁观测计划的最新数据,将其转换为两个要素类,并对其进行了符号化。然后,您将图层发布为要素服务。在下一课程中,您即将开发一个源例程以在珊瑚礁观测数据更新后立即自动下载其最新数据。


创建源例程

在上一课程中,您对 NOAA 珊瑚礁观测计划的最新数据执行了检索、制图和发布。数据显示固定时刻的珊瑚礁白化信息,但是数据会经常更新。如何能够在 NOAA 每次更新数据后,相应地快速更新您的地图呢?

在本课程中,您将开发一个源例程。源例程将自动下载内容,对内容进行处理并发布数据集。您的源例程将包括在上一课程中使用的 Python 工作流。

创建独立脚本

与上一课程的方法不同,此次您不在 ArcGIS Pro 中运行脚本,而是在文本编辑器中创建一个可以保存并通过单个命令运行的独立脚本。此脚本将包含您的源例程,并遵循聚合实时源 (ALF) 方法指南。

ALF 是用于在生产环境中部署 Live Feed 例程的指南、工具和函数。使用此工具可以在最小化监督的情况下自动化例程部署。ALF 方法包括了 Live Feed 例程的步骤,并添加了一些组件以优化常规工作流。这些组件添加了以下功能:将每一个运行步骤记录到日志、高效解压文件以及在发生故障时自动发送电子邮件。

注:

要了解有关 ALF 方法的详细信息,请参阅 Aggregated Live Feed Community 群组。您也可以下载并查看 Aggregated Live Feed Methodologies 文档。

  1. 在纯文本编辑器中打开一个文件。
    注:

    如果您没有纯文本编辑器,可以免费下载 Notepad++。您还可以使用 Python 集成开发环境 (IDE),例如,PyCharmPyScripterSpyder。本课程中的示例图像将使用 Notepad ++。

    首先,将文件保存为 Python 脚本文件。一些文本编辑器(包括 Notepad ++)会根据所使用的编程语言突出显示语法,这在编写代码时十分有用。

  2. 在功能区上,单击文件,然后选择保存另存为。文件将作为 coral_reef_exercise.py 保存到计算机上的某个位置。
    注:

    将文件另存为 Python 文件 (.py) 的过程可能会有所不同,具体取决于您所使用的程序。

    在上一课程中,针对最新数据制图时首先要执行的操作是导入 sys 模块,因此您将在源例程的开始添加执行这一操作的语句。

  3. 在文本编辑器中,创建 import sys 行。

    您还将定义一个名为 feedRoutine 的函数,该函数需要以下两个参数:url(数据的 URL)和 workGDB(您之前创建的文件地理数据库的路径) 稍后,您将定义此函数使其运行获取并针对数据制图的步骤,但是现在您将使用占位符 pass 为这些步骤占位。

    您还将添加 __name__ = "__main__" 语句,此语句会将脚本作为独立例程运行(例如,在命令提示符下运行脚本)。在这种情况下,独立脚本会通过 sys.argv[1:] 语句将 urlworkGDB 参数从命令提示符传递至 feedRoutine 函数以使其运行。

  4. 按两次 Enter 键。从第 3 行开始复制并粘贴以下行:
    def feedRoutine (url, workGDB):
        pass
    if __name__ == "__main__":
    	[url, workGDB] = sys.argv[1:]
    	feedRoutine (url, workGDB)
    注:

    缩进对于确保脚本正确运行而言十分重要。确保保留脚本中的所有缩进。请勿添加不必要的缩进。

    具有初始语句的源例程

    您在工作流中导入了多个其他模块。您已通过此函数使脚本导入所有必要的模块,而无需为每个模块再次运行导入语句。

  5. 将第 1 行 (import sys) 修改为 import sys, arcpy, os, tempfile, json。按 Enter 键并在第 2 行写入 from urllib import request

    完整的代码行如下所示:

    import sys, arcpy, os, tempfile, json
    from urllib import request

    具有所有模块的源例程

    接下来,您要将 pass 占位符替换为检索数据和创建图层所需的步骤。首先,您需要将 workGDB 定义为默认地理数据库 (arpy.env.workspace) 然后使用 arcpy.management.CreateFileGDB 函数创建地理数据库。

  6. 将第 5 行 (pass) 替换为以下行:
    # workGDB and default workspace
        arcpy.env.workspace = workGDB 
        arcpy.management.CreateFileGDB(os.path.dirname(workGDB), os.path.basename(workGDB))
    注:

    根据您的窗口大小的不同,一些较长的行可能会换行,如下图所示:

    已定义默认地理数据库的源例程

    接下来,您将为部署逻辑函数添加占位符代码。您现在并不需要此函数,但是为了供后续课程使用,最好在您的脚本中为其添加位置。您还要为上一课程中使用的代码添加占位符。

  7. 在第 7 行后,按两次 Enter 键并移除所有缩进。从第 9 行开始,复制并粘贴以下行(包括缩进)。
    ### Placeholder for retrieving and mapping data ###
        # Deployment Logic
        deployLogic()
        # Return
        return True
    def deployLogic():
        pass

    具有部署逻辑的占位符的源例程

    注:

    缩进应使用空格而不是制表符,这一点十分重要。

    接下来,您将使用在上一课程中运行的代码替换占位符以检索并针对数据进行制图。

    此代码将不包括用于更改符号系统的代码。图层的符号系统已保存在您的 ArcGIS Pro 工程和 web 地图中,因此您无需再次更改符号系统。(用于添加和计算 alert_level 字段的代码将保留,因为现有的符号系统需要这些字段。)

    另外,此代码将包括多个包含语句的 print() 函数,使您能够及时了解正在运行哪些代码行。

  8. 将第 9 行 (### Placeholder for retrieving and mapping data ###) 替换为以下行:
    # Download and split json file
        print("Downloading data...")
        temp_dir = tempfile.mkdtemp()
        filename = os.path.join(temp_dir, 'latest_data.json')
        response = request.urlretrieve(url, filename)
        with open(filename) as json_file:
            data_raw = json.load(json_file)
            data_stations = dict(type=data_raw['type'], features=[])
            data_areas = dict(type=data_raw['type'], features=[])
        for feat in data_raw['features']:
            if feat['geometry']['type'] == 'Point':
                data_stations['features'].append(feat)
            else:
                data_areas['features'].append(feat)
        # Filenames of temp json files
        stations_json_path = os.path.join(temp_dir, 'points.json')
        areas_json_path = os.path.join(temp_dir, 'polygons.json')
        # Save dictionaries into json files
        with open(stations_json_path, 'w') as point_json_file:
            json.dump(data_stations, point_json_file, indent=4)
        with open(areas_json_path, 'w') as poly_json_file:
            json.dump(data_areas, poly_json_file, indent=4)
        # Convert json files to features
        print("Creating feature classes...")
        arcpy.conversion.JSONToFeatures(stations_json_path, 'alert_stations') 
        arcpy.conversion.JSONToFeatures(areas_json_path, 'alert_areas')
        # Add 'alert_level ' field
        arcpy.management.AddField('alert_stations', 'alert_level', 'SHORT', field_alias='Alert Level')
        arcpy.management.AddField('alert_areas', 'alert_level', 'SHORT', field_alias='Alert Level')
        # Calculate 'alert_level ' field
        arcpy.management.CalculateField('alert_stations', 'alert_level', "int(!alert!)")
        arcpy.management.CalculateField('alert_areas', 'alert_level', "int(!alert!)")

    接下来,您将向脚本的其他部分再添加三个 print() 函数,包括用于在脚本执行完成时向您发出通知的函数。

  9. 在第 5 行 (# workGDB and default workspace) 后按 Enter 键。在第 6 行删除现有缩进并创建以下行:
    print("Creating workGDB...")

    已将 print() 函数添加到 workGDB 代码块的源例程

  10. 在第 43 行 (# Deployment Logic) 后按 Enter 键。在第 44 行删除现有缩进并创建以下行:
    print("Deploying...")
  11. 在第 47 行 (# Return) 后,按 Enter 键。在第 48 行删除现有缩进并创建以下行:
    print("Done!")

    根据您创建脚本的方式不同,可能还会存在制表符缩进。

  12. 检查您的整个脚本,以确保所有缩进均使用空格而非制表符。
    提示:

    如果您正在使用 Notepad++,您可以自动将制表符转换为空格。在功能区中,单击编辑,指向空白字符操作,然后选择TAB 转空格

  13. 保存脚本。
    注:

    如果要确认是否已正确创建脚本,可以将其与示例脚本进行对比。

    接下来,您将测试脚本。

  14. 打开 Windows“开始”菜单。搜索并打开 Python 命令提示符。

    首先,您将浏览至保存 coral_reef_exercise.py 文件目录。

    注:

    对于示例图像,coral_reef_exercise.py 将保存在 Documents 文件夹中 (C:\Users\Documents)。您可以在文件浏览器(Windows 资源管理器)中浏览至文件以获取路径,并将其复制。

  15. 在 Python 命令提示符中,输入 cd 并按空格键。将保存 Python 文件的路径粘贴至目录。如果路径包含空格,请在路径前后添加引号。

    带有更改目录命令的 Python 命令提示符

  16. Enter 键。

    目录已更改。接下来,您将运行脚本。您将使用 python 命令,其中包括文件名、包含珊瑚礁数据的网站的 URL 以及地理数据库的路径和名称。

  17. 运行以下命令:

    python coral_reef_exercise.py https://coralreefwatch.noaa.gov/vs/vs_polygons.json C:\Temp\Work.gdb

    运行此命令需要花费一些时间。运行命令的同时,您可通过 print() 函数了解其进度。

    具有独立脚本的 Python 命令提示符

    工作地理数据库中的图层将使用最新数据进行更新(可能与您在上一课程中使用的数据相同)。目前,脚本不会更新 ArcGIS Pro 工程中和 web 地图中显示的地图。稍后您将使用 deployLogic() 函数添加此功能。

添加高级脚本功能

您的脚本有效,但是可以进行改进。首先,您将调整脚本以便在不存在地理数据库时进行创建。

您将使用 arcpy.Exists 函数创建 if 语句,以检查是否存在工作空间。如果存在,您将删除所有以 alert_ 开头的要素类,以便它们可以被新的要素类替换。您可以使用 alert_* 字符串和可以代替任何文本的星号来表示两个警报图层。

  1. 如有必要,在文本编辑器中打开 coral_reef_exercise 脚本。
  2. 将第 5 行到第 8 行(用于创建默认工作空间的代码行)替换为以下行:
    # Create workGDB and default workspace
        print("Starting workGDB...")
        arcpy.env.workspace = workGDB
        if arcpy.Exists(arcpy.env.workspace):
            for feat in arcpy.ListFeatureClasses ("alert_*"):   
                arcpy.management.Delete(feat)
        else:
            arcpy.management.CreateFileGDB(os.path.dirname(workGDB), os.path.basename(workGDB))

    用于检查现有 workGDB 的高级脚本

    如果在无 Internet 访问的电脑上运行脚本,则无法下载在线 JSON 文件。要捕获此常见错误,您将提出标准异常 URLError,通知用户 URL 不可用。

  3. 将第 18 行 (response = request.urlretrieve(url, filename)) 替换为以下行:
    try:
            response = request.urlretrieve(url, filename)
        except URLError:
            raise Exception("{0} not available. Check internet connection or url address".format(url))

    提出 URLError 的高级脚本

    接下来,您将在日志文件中记录运行步骤。您已在命令提示符中打印了关于脚本每个部分的消息,因此您需要在每个 print() 函数后添加 logging.info() 函数。如果脚本出现错误,此函数会记录可能对调试有用的消息。您记录的消息将包括记录该消息的日期和时间。

    首先,您将修改脚本以导入 loggingdatetime 模块。您还将导入之前使用的 URLError 异常。

  4. 将第 1 行和第 2 行(导入行)替换为以下行:
    import sys, os, tempfile, json, logging, arcpy
    import datetime as dt
    from urllib import request
    from urllib.error import URLError

    接下来,您将使用 logging.basicConfig() 函数配置将用于记录消息的日志文件。您还将设置用于定义日期和时间的显示格式的 log_format 变量。

  5. 在第 6 行 (def feedRoutine) 后添加以下行:
    # Log file
        logging.basicConfig(filename="coral_reef_exercise.log", level=logging.INFO)
        log_format = "%Y-%m-%d %H:%M:%S"

    用于配置日志的高级脚本

    接下来,您将添加用于将消息添加到日志的 logging.info() 函数。这些函数将通过 dt.datetime.now() 函数记录日期和时间并使用您之前创建的 log_format 变量设置日期和时间的格式。您将在每个 print() 函数后添加这些函数。

  6. 在第 11 行 (print("Starting workGDB...")) 后添加以下行:
    logging.info("Starting workGDB... {0}".format(dt.datetime.now().strftime(log_format)))
  7. 在第 21 行 (print("Downloading data...")) 后添加以下行:
    logging.info("Downloading data... {0}".format(dt.datetime.now().strftime(log_format)))
  8. 在第 47 行 (print("Creating feature classes...")) 后添加以下行:
    logging.info("Creating feature classes... {0}".format(dt.datetime.now().strftime(log_format)))
  9. 在第 59 行 (print("Deploying...")) 后添加以下行:
    logging.info("Deploying... {0}".format(dt.datetime.now().strftime(log_format)))
  10. 在第 64 行 (print("Done!")) 后添加以下行:
    logging.info("Done! {0}".format(dt.datetime.now().strftime(log_format)))

    您还将使用 logging.exception() 函数记录 URLError 异常。

  11. 在第 27 行 (except URLError) 后添加以下行:
    logging.exception("Failed on: request.urlretrieve(url, filename) {0}".format(
                              dt.datetime.now().strftime(log_format)))

    最后,您将在脚本末尾处使用 logging.shutdown() 函数关闭日志文件。

  12. 在第 63 行的末尾按两次 Enter 键并删除新行中的任何缩进。第 65 行添加以下行:
    # Close Log File
        logging.shutdown()

    用于关闭日志文件的高级脚本

  13. 确保您的脚本不包含任何制表符缩进。保存您的脚本。
    注:

    如果要确认是否已正确创建脚本,可以将其与示例脚本进行对比。

在本课程中,您使用命令提示符创建了一个可以作为独立脚本运行的源例程。您还添加了一些高级功能。在下一课程中,您将调整源例程以更新 ArcGIS Pro 工程中的本地要素类。


更新本地要素类

在上一课程中,您创建了源例程。此例程在运行时会下载最新的 NOAA 珊瑚白化数据并创建两个要素类,其中一个用于点数据,另一个用于面数据。这些要素类位于 Work 地理数据库中。然而,此脚本不会更新您的 ArcGIS Pro 工程中的图层,这些图层位于 Live 地理数据库中。

在本课程中,您将调整您的源例程,使其自动更新您的 ArcGIS Pro 工程中的 alert_stations 和 alert_areas 图层。

定义部署逻辑函数

您的源例程包含名为 deployLogic() 的部署逻辑函数的占位符。在 ALF 方法中,部署逻辑过程是源例程的一部分,它将从 Internet 检索最新信息(在您的案例中,数据位于 Work 地理数据库)并覆盖实时数据(位于 Live 数据库中的要素类)。

  1. 创建您的 coral_reef_exercise.py 脚本的副本,命名为 coral_reef_exercise_local.py。在文本编辑器或 Python IDE 中打开副本。

    接下来,您将修改脚本以导入 shutil 模块。此模块包含多个定义部署逻辑函数必需的高级文件操作。

  2. coral_reef_exercise_local.py 脚本的第 1 行中,将 shutil 添加至模块列表。

    导具有 shutil 模块的导入函数

    接下来,您将函数添加名为 liveGDB 的第三个参数,其表示您的工程中的图层所在的 Live 地理数据库。

  3. 在第 6 行处,将 liveGDB 添加到 feedRoutine 参数列表。

    具有 liveGDB 参数的源例程

    您还要将此参数添加到脚本末尾的 sys.argv[1:] 命令。这样,用户即可在命令提示符下运行脚本时提供 Live 地理数据库的路径和名称。

  4. 在第 77 行处,将 liveGDB 添加到括号中的列表。在第 78 行处,将 liveGDB 添加到 feedRoutine 参数列表。

    具有附加 liveGDB 参数的源例程

    deployLogic() 函数将采用两个参数,workGDBliveGDB,因此您可以在对函数进行调用和定义的位置添加这些参数。

  5. 在第 63 行和第 73 行处,将 deployLogic() 替换为 deployLogic(workGDB, liveGDB)

    具有 deployLogic() 参数的源例程

    接下来,您将定义 deployLogic() 函数。您将使用 for 循环复制 workGDB 参数中的所有元素并使用它们来替换 liveGDB 中的元素。您将使用 os.walk() 函数列出文件并使用 shutil.copy2() 函数进行复制和替换。根据 ALF 方法,您将令脚本忽略所有 .lock 文件。

  6. 在第 74 行处,将 pass(占位符)替换为以下行:
    for root, dirs, files in os.walk(workGDB, topdown=False):
    	    files = [f for f in files if '.lock' not in f]
    	    for f in files:
    	        shutil.copy2(os.path.join(workGDB, f), os.path.join(liveGDB, f))

    用于定义 deployLogic() 函数的脚本

    注:

    此源例程将自动替换您的 ArcGIS Pro 工程中的要素类,但是有必要采取一些预防措施。新的要素类必须与之前的数据结构保持一致;字段缺失或名称不同均会破坏地图工程。

  7. 确保您的脚本不包含任何制表符缩进。保存您的脚本。
    注:

    如果要确认是否已正确创建脚本,可以将其与示例脚本进行对比。

运行独立脚本

接下来,您将运行调整过的源例程并更新 ArcGIS Pro 工程。

可能自从您的工程使用最新数据制图后,NOAA 尚未更新其数据。如果您现在运行脚本,可能不会看到数据发生任何变化。要测试您的脚本函数是否正确运行,您将使用由 Learn ArcGIS 托管的历史文件更新数据。

  1. 如有必要,在 ArcGIS Pro 中打开您的 Coral Bleaching 工程。
  2. 如有必要,打开 Python 命令提示符并使用 cd 命令浏览至保存 coral_reef_exercise_local.py 文件的目录。
  3. 在命令提示符中,运行以下命令:

    python coral_reef_exercise_local.py https://downloads.esri.com/LearnArcGIS/update-real-time-data-with-python/vs_polygons.json C:\Temp\Work.gdb C:\Temp\Live.gdb

    命令随即运行。

    运行命令的 Python 命令提示符

    注:

    NOAA 珊瑚礁观测计划更新其数据后,您可以将历史文件的 URL (https://downloads.esri.com/LearnArcGIS/update-real-time-data-with-python/vs_polygons.json) 更换为 NOAA 数据的 URL (https://coralreefwatch.noaa.gov/vs/vs_polygons.json)。

    尽管提示符表明命令已成功执行,但 ArcGIS Pro 中的地图未发生任何更改。您将重新启动 ArcGIS Pro 并刷新地图显示以可视化更改。

  4. 关闭 ArcGIS Pro(如出现提示,请保存)。重新打开 Coral Bleaching 工程。

    重新启动 ArcGIS Pro 可能也会刷新地图显示。如果未刷新,请手动刷新显示。

  5. 如有必要,在地图视图的右下角单击刷新按钮。

    “刷新”按钮

    地图刷新并显示历史数据(2019 年 2 月 19 日的数据)。

    具有历史数据的地图

    您也可以验证属性数据是否已更新。

  6. 在地图上,单击任一站点或区域要素。

    要素的弹出窗口随即打开。date 字段显示 2019-02-19,即历史数据的日期。

    具有历史信息的弹出窗口

  7. 关闭弹出窗口。

在本课程中,您开发并运行了一个用于更新本地数据集的源例程。您通过使用历史数据更新地图来测试了源例程,通过替换 Python 命令中使用的 URL,您可以对 NOAA 的最新数据执行相同的过程。在下一课程中,您将开发并运行类似的源例程以更新在线要素服务。


更新在线要素服务

在上一课程中,您开发并运行了用于更新 ArcGIS Pro 工程中的本地要素类的源例程。在本课程中,您将按照类似的过程开发并运行用于更新 web 地图中的在线要素服务的源例程。

获取服务定义和 ID

当更新本地要素类时,您使用了 Live 地理数据库作为复制新数据的目标位置。在线要素服务不存储于地理数据库中,因此您需要服务定义文件和项目 ID 以使用 ArcGIS API for Python 来查询并替换要素服务。

在第一课中,您发布了包含最新数据的要素服务。您将使用此要素服务作为要更新的目标。首先,您将下载其服务定义文件。

  1. 如有必要,登录到您的 ArcGIS 组织帐户ArcGIS Enterprise 门户。
  2. 转至内容页面并访问存储 Coral Reef Watch 要素图层和服务定义文件的文件夹。
    注:

    当您发布图层时,会创建服务定义文件。由于您将使用此文件更新要素服务,因此在更新要素服务后,所有在其发布后做出的更改(例如元数据或符号系统更改)都将丢失。所有包括要素服务的 web 地图和应用程序也会受到影响。

    要避免对要素服务的更改丢失,建议的做法是创建查看图层。使用要素图层的任何 web 地图和应用程序都可以指向查看图层而不指向要素服务,因此当要素服务更新时,将保留对查看图层的更改。要创建查看图层,打开要素图层的详细信息页面并单击创建查看图层。您可以通过查看文档页面找到详细信息。

  3. 对于Coral Reef Watch 服务定义文件,选择下载

    下载服务定义文件

    服务定义文件 (.sd) 已下载到您的计算机。

  4. 将服务定义文件复制到 C 盘中的 Temp 文件夹。

    接下来,您将复制图层的项目 ID。

  5. 对于 Coral Reef Watch 要素图层,单击选项按钮并选择 查看项目详细信息

    要素图层的详细信息页面随即显示。ID 位于 URL 中。

  6. 再详细信息页面的 URL 中,复制 id= 后的的字母数字字符串(在示例图片中,此字符串为 2dcf249f5cd54a609d51acba6e0ba029)。
    注:

    您的要素图层的项目 ID 会有所不同。

    要素图层的项目 ID

  7. 将 ID 复制到空白的文本文件中或者您可以轻松访问的位置。

定义部署逻辑函数

接下来,您将创建原始源例程的另一个副本。然后,您将使用脚本定义 deployLogic() 函数,它将使用从 Work 地理数据库下载的数据替换在线要素服务。

  1. 创建您的原始 coral_reef_exercise.py 脚本的副本,命名为 coral_reef_exercise_online.py。在文本编辑器或 Python IDE 中打开副本。

    对于您创建的脚本,将需要 fnmatchshutilsubprocessarcgis 模块和 GIS 子模块。

  2. coral_reef_exercise_online.py 脚本中的第 1 行处,向模块列表中添加 fnmatchshutilsubprocessarcgis。按 Enter 键并在第 2 行添加 from arcgis.gis import GIS

    完整的代码行如下所示:

    import sys, os, tempfile, json, logging, arcpy, fnmatch, shutil, subprocess, arcgis
    from arcgis.gis import GIS

    包含导入模块和子模块代码行的源例程

    当您定义部署逻辑函数以添加本地要素类时,您向源例程添加了名为 liveGDB 的参数,以便其在运行脚本时提供必需的地理数据库的路径。对于此源例程,您为要素服务的项目 ID、服务定义文件和服务名称添加参数。

  3. 在第 7 行处,向 feedRoutine 参数列表添加参数 itemidoriginal_sd_fileservice_name

    完整的代码行如下所示:

    def feedRoutine (url, workGDB, itemid, original_sd_file, service_name):

    添加至 feedRoutine 函数的参数

    您还要将这些参数添加到脚本末尾的 sys.argv[1:] 命令中。

  4. 在第 78 和第 79 行处,向两个参数列表添加参数 itemidoriginal_sd_fileservice_name

    完整的代码行如下所示:

    [url, workGDB, itemid, original_sd_file, service_name] = sys.argv[1:]
        feedRoutine (url, workGDB, itemid, original_sd_file, service_name)

    添加到 sys.argv[1:] 命令的参数

    您还要在进行定义和调用的位置为 deployLogic() 函数添加这些参数(和 workGDB 参数)。

  5. 在第 64 行和第 74 行处,将 deployLogic() 替换为 deployLogic(workGDB, itemid, original_sd_file, service_name)

    deployLogic 函数在定义和调用位置处的参数

    接下来,您将定义 deployLogic() 函数。此函数将完成多个任务。首先,它将使用 gis.content.get() 函数从 ArcGIS Online 或您的 ArcGIS Enterprise 门户(由 itemid参数表示)获取要素服务项目。

    您还将创建由 GIS() 函数定义的 gis 变量。此函数的参数将包含您组织门户的 URL(对于 ArcGIS Online, 此 URL 为 https://arcgis.com)、您的帐户用户名和帐户密码。

  6. 在第 75 行处,将占位符脚本 (pass) 替换为以下行:
    # Get item from ArcGIS Online
        gis = GIS(url='https://arcgis.com', username='your_username', password='your_password')
        item = gis.content.get(itemid)
        sd_file_name = os.path.basename(original_sd_file)
        if sd_file_name != item.related_items("Service2Data")[0].name:
            raise Exception('Erroneous itemid, service name, or original sd file'.format(itemid))
    注:

    如果您正在使用 ArcGIS Online 帐户,则 url 参数为可选项。

  7. 在第 76 行处,将 usernamepassword 参数更换为您的 ArcGIS 帐户用户名和密码。如果您使用的是用于 ArcGIS Enterprise 门户的帐户,将 url 参数替换为门户的 URL。
    警告:

    由于此脚本包含您的密码,请谨慎将脚本与其他人共享。有高级的脚本功能可以帮助您保护您的凭据

    接下来,deployLogic() 函数将解压服务定义文件 (original_sd_file) 的内容。函数将使用 7-Zip 执行此操作,许多 Windows 计算机默认附带此程序。在添加将使用 7-Zip 解压文件的脚本之前,您将确保计算机已具有此程序并将其添加到 Windows Path 环境变量中。通过将其添加到这一环境变量中,您将能够使用脚本进行调用。

  8. 如有必要,为您的计算机下载适当版本的 7-Zip 并进行安装。

    编辑环境变量的方法可能不同,具体取决于您使用的操作系统,但是通常可以通过环境变量窗口完成此操作。

  9. 在计算机上打开控制面板。单击系统和安全,单击系统,然后单击高级系统设置。在系统属性窗口中,单击环境变量。(精确的路径可能根据您的操作系统而有所不同。)
  10. 环境变量窗口中,对于系统变量,选择 Path 变量并单击编辑

    根据您所使用的操作系统,随即打开编辑环境变量编辑系统变量窗口。对于每个窗口,添加新变量的过程有所不同。

  11. 如果编辑环境变量窗口打开,单击新建并添加 C:\Program Files\7-Zip 作为新变量。如果编辑系统变量窗口打开,滚动至变量值参数末尾,并在末尾粘贴 ;C:\Program Files\7-Zip(确保不会删除任何现有文本)。
  12. 单击确定。在环境变量窗口中,单击确定

    接下来,您将创建脚本。将包含一个当 7-Zip 无法在 Path 环境变量中找到时提示的错误消息。

  13. coral_reef_exercise_online.py 脚本中的第 80 行后,添加以下行:
    # Unpack original_sd_file using 7-zip
        path_7z = fnmatch.filter(os.environ['path'].split(';'), '*7-Zip')
        temp_dir = tempfile.mkdtemp()
        if len(path_7z):
            exe_7z = os.path.join(path_7z[0], '7z.exe')
            call_unzip = '{0} x {1} -o{2}'.format(exe_7z, original_sd_file, temp_dir)
        else:
            raise Exception('7-Zip could not be found in the PATH environment variable')
        subprocess.call(call_unzip)

    在脚本获取要素服务并解压其服务定义文件后,您需将其数据更换为下载至 Work.gdb 的数据。您将使用 Live.gdb 作为可以压缩至新的服务定义文件的中介文件夹。

    您的脚本将使用 shutil.rmtree() 函数以删除 Live.gdb,而 os.mkdir() 函数会将其再次创建并移除数据库中的所有现有内容。

  14. 在第 89 行后添加以下行:
    # Replace Live.gdb content
        liveGDB = os.path.join(temp_dir, 'p20', 'live.gdb')
        shutil.rmtree(liveGDB)
        os.mkdir(liveGDB)
        for root, dirs, files in os.walk(workGDB):
            files = [f for f in files if '.lock' not in f]
            for f in files:
                shutil.copy2(os.path.join(workGDB, f), os.path.join(liveGDB, f))

    接下来,脚本会将 Live.gdb 压缩至新的要素定义文件,称为 updated_sd

  15. 在第 97 行后添加以下行:
    # Zip file
        os.chdir(temp_dir)
        updated_sd = os.path.join(temp_dir, sd_file_name)
        call_zip = '{0} a {1} -m1=LZMA'.format(exe_7z, updated_sd)
        subprocess.call(call_zip)

    最后,脚本将使用项目的 manager 方法 (arcgis.features.FeatureLayerCollection.fromitem(item).manager) 以使用新数据覆盖要素服务。

  16. 在第 102 行后添加以下行:
    # Replace file
        manager = arcgis.features.FeatureLayerCollection.fromitem(item).manager
        status = manager.overwrite(updated_sd)
        # Return
        return True
  17. 确保您的脚本不包含任何制表符缩进。保存您的脚本。
    注:

    如果要确认是否已正确创建脚本,可以将其与示例脚本进行对比。

运行独立脚本

接下来,您将在 Python 命令提示符中运行源例程并更新 Coral Reef Watch 在线要素服务。与上一课程类似,您将使用历史数据更新要素服务以进行练习。

  1. 如有必要,在 ArcGIS Online 或您的 ArcGIS Enterprise 门户中,在 Map Viewer 中打开 Coral Reef Watch 要素图层。
  2. 如有必要,打开 Python 命令提示符并使用 cd 命令浏览至保存 coral_reef_exercise_local.py 文件的目录。
    注:

    如果您已将 7-Zip 添加到 Path 环境变量中,您可能需要重新启动 Python 命令提示符。

  3. 粘贴以下命令(先不要运行):

    python coral_reef_exercise_online.py https://downloads.esri.com/LearnArcGIS/update-real-time-data-with-python/vs_polygons.json C:\Temp\Work.gdb

    运行命令之前,您将添加所需的其余参数:项目 ID、原始服务定义文件和服务名称。

  4. 在命令的末尾,按空格键并粘贴要素服务的项目 ID。
    注:

    项目 ID 是字母和数字的字符串,位于要素服务的 URL 中(例如,2dcf249f5cd54a609d51acba6e0ba029)。

    之前,您已下载原始服务定义文件并将其复制到您的 Temp 文件夹中。服务名称为 Coral_Reef_Watch

  5. 按空格键并粘贴 C:\Temp\Coral_Reef_Watch.sd Coral_Reef_Watch

    您的完整命令的格式与以下命令类似(但是具有不同的项目 ID):

    python coral_reef_exercise_online.py https://downloads.esri.com/LearnArcGIS/update-real-time-data-with-python/vs_polygons.json C:\Temp\Work.gdb 2dcf249f5cd54a609d51acba6e0ba029 C:\Temp\Coral_Reef_Watch.sd Coral_Reef_Watch

    Python 命令提示符中的命令示例

  6. 运行命令。

    命令随即运行。命令提示符返回有关 7-Zip 和正在提取的数据的大量信息。当命令完成后,命令提示符将返回此行 Done

    命令提示符返回“完成”

    接下来,您将可视化 web 地图上的更改。

  7. 使用您的浏览器的刷新重新加载按钮刷新您的 web 地图。

    地图将使用 2019 年 2 月 19 日的数据进行更新。

    包含 2019 年 2 月 19 日的数据的最终地图

  8. 单击任意观测站或区域以打开其弹出窗口。

    Date 字段显示 2019-02-19,确认数据已正确更新。

    弹出窗口中的日期字段

  9. 关闭弹出窗口。关闭 Web 地图但不保存。(如果您愿意,也可以保存 web 地图。)

在本课程中,您创建了用于使用最新 NOAA 数据自动更新本地和 web 图层的源例程。本课程还介绍了基本和高级 Python 主题并使用 ALF 方法开发和实现了源例程。出于本课程的目的,您使用历史数据更新了图层,但是您可以使用 NOAA 数据的 URL 运行相同的脚本。

您可以经常运行此脚本以使您的图层保持最新。通过在 Windows 中设置任务,您可以使脚本以特定间隔自动运行,使其可以使用实时数据进行部署。

您可以在 Learn ArcGIS 课程库中找到更多课程。