使用 Python 列出和描述数据集
打开工程和查看数据集
开始使用 Python 列出和描述数据集之前,您将下载并提取工程数据的 .zip 文件,并在 ArcGIS Pro 中查看数据集。
- 下载本教程数据,并将内容提取到您的计算机上的某一位置。
.zip 文件包含名为 PythonDesc 的文件夹。
在本教程中,数据显示在 C:\Lessons\PythonDesc\ 位置。 您可以使用其他文件夹,但是请确保按照以下说明和代码调整路径。
- 启动 ArcGIS Pro。
- 在 ArcGIS Pro 中的新建工程下,单击从没有模板的情况入手。
随即打开一个名为 Untitled 的新工程。 您将仅使用 ArcGIS Pro 查看数据,因此无需重命名工程和保存工作成果。
- 如果目录窗格尚不可见,请单击视图选项卡,然后单击目录窗格。
- 在目录窗格中,右键单击文件夹,然后单击添加文件夹连接。
- 在添加文件夹连接窗口中,浏览至 PythonDesc.zip 文件的提取位置(C:\Lessons),单击 PythonDesc 文件夹,然后单击确定。
- 在目录窗格中,展开文件夹,然后展开 PythonDesc。
文件夹包含两个 shapefile(bike_routes.shp 和 watersheds.shp)、一个文本文件 (bike_racks.csv) 和一个数据库表 (gardens.dbf)。 还包含一个名为 DC.gdb 的地理数据库。
- 展开 DC.gdb。
地理数据库包含三个要素类(boundary、neighborhoods 和 public_schools)、一个表 (car_share_locations) 和一个要素数据集 (Transportation)。
- 展开 Transportation。
要素数据集包含四个要素类(roads、street_lights、traffic_analysis_zones 和 traffic_junctions)以及一个网络数据集 (traffic)。
数据集是 GIS 工程的典型内容,包含不同格式的要素类和表格数据,以及组织这些数据的其他元素。 您将使用 Python 代码基于其类型和其他属性识别这些数据集。 请注意,这些分组意味着工程数据具有多级别嵌套结构。
使用 Python 代码之前,您还将查看计算机上的实际文件以浏览这些数据集。
- 打开 Microsoft File Explorer,然后浏览至 C:\Lessons\PythonDesc\ 文件夹或存放 PythonDesc 文件夹的其他位置。
File Explorer 将显示文件。 两个独立表(bike_racks.csv 和 gardens.dbf)为单个文件。 每个 shapefile(bike_routes 和 watersheds)均由具有相同名称和不同文件扩展名的多个文件组成。 DC 地理数据库是文件扩展名为 .gdb 的文件夹。
- 在 File Explorer 中,展开 DC.gdb 文件夹。
此文件夹中有几十个文件。 在 ArcGIS Pro 中的目录窗格中查看地理数据库时,这些文件和可见的数据元素之间没有可以清楚识别的链接。 例如,您无法识别组成一个特定要素类的一个或多个文件。 这一点对于在 Python 代码中使用 GIS 数据集十分重要,因为这会影响如何访问和使用不同格式的数据集。
打开 Python 脚本文件
在本教程中,您将使用 IDLE 编写 Python 代码。 IDLE 是 ArcGIS Pro 随附的基础 Python 编辑器。
要确保使用随 ArcGIS Pro 安装的正确版本的 Python 运行您的代码,您将使用快捷方式启动 IDLE。
如果您已安装 ArcGIS Desktop (ArcMap),则快捷菜单中还将包含快捷选项使用 IDLE 编辑。 请勿使用此快捷选项;因为它将打开旧版本的 Python。
- 在 File Explorer 中,返回到上一级的 C:\Lessons\PythonDesc\ 文件夹。
- 右键单击 describe_data.py,然后单击使用 IDLE 编辑(ArcGIS Pro)。
通过此方式打开 IDLE 会使用 ArcGIS Pro 的活动 Python 环境打开脚本。 这样可以确保使用正确版本的 Python。 虽然本教程使用 IDLE 作为代码编辑器,但是代码也可用于其他 Python 编辑器(例如 PyCharm 或 Spyder)、Python 窗口或 ArcGIS Pro 中的 Notebooks。
注:
如果使用 IDLE 编辑(ArcGIS Pro)在快捷菜单中不可见,单击开始,展开 ArcGIS,然后单击 Python 命令提示符。 在 Python 命令提示符窗口中,输入 idle 并按 Enter 键。 IDLE (Python 3.7 Shell) 随即显示。 单击文件,然后单击打开。 浏览至 describe_data.py 文件,然后将其打开。脚本将打开。
脚本包含三行代码作为开头。 第一行为 import arcpy,用于导入 ArcPy 包。 此代码将确保可在脚本中使用 ArcPy 的功能,包括用于列出和描述 GIS 数据集的函数。
第二行用于指定数据所在的路径。 此值分配给一个名为 mypath 的变量。
路径中使用单个正斜线 (/) 而非单个反斜线 (\)。 Python 中的单个反斜线用作转义字符,在路径中使用此符号可能导致意外结果。 当字符后存在某些其他字符时,会编译为特殊行为。 例如,\t 表示选项卡,类似 C:\Lessons\toronto.gdb 的路径会在路径中添加一个选项卡,进而导致错误。
除了单个正斜线,您也可以在字符串 (r"C:\Lessons\PythonDesc") 之前添加字母 r(表示原始),或使用双反斜线 ("C:\\Lessons\\PythonDesc")。 三种符号均有效。
第三行用于设置工作空间。 工作空间是将要使用的文件(例如输入和输出数据集)的默认位置。 工作空间已设置为 mypath 变量。 虽然可以不使用 mypath 变量直接设置工作空间,但为数据所在的路径使用单独的变量有许多益处。
- 如果您未将 PythonDesc 文件夹保存在 C:\Lessons\PythonDesc\ 位置,则需在脚本中编辑路径以指向保存文件夹的位置。
例如,如果您将本教程的数据提取至文件夹 C:\EsriLessons,则应编辑第二行,使其如下所示:
mypath = "C:/EsriLessons/PythonDesc"
如果您的路径相对较长,则可以从文件资源管理器复制路径并粘贴到脚本中。 为此,您可以右键单击文件夹 (Windows 11) 或按住 Shift 并右键单击文件夹 (Windows 10),然后单击复制为路径。 然后,您可以从脚本中选择并删除旧路径,并按 Ctrl+V 粘贴新路径。
要使用路径作为有效工作空间,路径必须为 Python 字符串,这意味着路径周围必须有引号。 您还需要使用上方提及的三种正确的路径样式之一。 如果复制了 Windows 路径,则路径中将包含反斜线。 您可以将每处单个反斜线替换为两个反斜线或单个正斜线。 对于长路径,最简单的解决方案是在字符串之前添加 r,以使其作为原始字符串。 这样可以确保反斜线不被读作转义字符。
现在,您将测试代码。
- 单击文件,然后单击保存。
- 单击运行,然后单击运行模块。
随即出现 IDLE Shell 窗口,显示一条消息,指示已为您的脚本重新启动 shell。 脚本路径和文件名称随即显示。 几秒钟的停顿后,将返回 IDLE Shell 提示符 >>>。
看起来似乎什么也没发生,因为脚本没有任何将数据打印到 shell 的指令。 稍后,您会将打印语句添加到代码,以将信息返回至 shell。
您也可以在 IDLE Shell 中输入代码行,然后直接运行。
- 在 IDLE Shell 中,在提示符 >>> 后,输入 print(arcpy.env.workspace) 然后按 Enter。
您在脚本中设置的工作空间路径将打印至 IDLE Shell。 脚本导入了 arcpy 模块,将 mypath 变量设置为等于包含教程数据路径的字符串,并将 arcpy 的工作空间设置为该路径。 通过在 shell 中打印 arcpy.env.workspace 的值,您证明了该脚本可以正常运行。
- 关闭 IDLE Shell 窗口。
设置工作空间后,您可以使用文件名引用数据集,而无需使用完整路径。
使用 Python 描述数据集
现在,脚本设置了工作空间,您可以使用 Python 描述该工作空间内某个数据集的属性。
为此,您将使用 da.Describe() 函数。
- 在 IDLE 编辑器窗口中,在 arcpy.env.workspace = mypath 行后单击,然后按 Enter 键以添加新行。
- 输入以下代码,然后按 Enter 键:
desc = arcpy.da.Describe("bike_routes.shp")
da.Describe() 函数是 arcpy.da 模块的一个函数,用于数据访问工作流。 此函数将返回一个 Python 字典。 Python 字典由成对的键及其对应值构成。 da.Describe() 返回的字典中的键是数据集的属性。
- 在 desc = arcpy.da 行后添加一个新代码行,添加以下代码并按 Enter 键:
print(f'baseName: {desc["baseName"]}')
脚本运行时,将打印属性 baseName 的值。 在上方的代码行中,desc 是属性的字典,baseName 是字符串形式的键。 表达式 desc["baseName"] 将返回字典中与此键关联的值。
此处使用的打印格式样式称为 f 字符串。 F 字符串也称为格式化字符串字面值。 它们是以字母 f 为前缀的字符串,并且使用大括号包含变量。 代码运行时,这些变量将替换为对应的值。 在上方示例代码中,在值 baseName 周围使用了双引号以将其用作字符串。 由于引号也适用于 f 字符串,因此有必要使用单引号,以便与双引号区分开来。 在 Python 中,只要在使用时保持一致,这些不同类型的引号即可互换使用。
以下内容同样正确:
print(f"baseName: {desc['baseName']}")
到目前为止,完整代码如下所示:
import arcpy mypath = "C:/Lessons/PythonDesc" arcpy.env.workspace = mypath desc = arcpy.da.Describe("bike_routes.shp") print(f'baseName: {desc["baseName"]}')
如果您将数据存储在其他位置,则 mypath 代码行将有所不同。
- 单击文件,然后单击保存以保存脚本。
您也可以使用键盘快捷键 Ctrl+S。
- 单击运行,然后单击运行模块。
IDLE Shell 窗口随即出现,显示的结果如下:
baseName: bike_routes
数据的基本名称是不包含文件扩展名的文件名称。
在学习如何编写代码时,经常会遇到错误。 在下一步中,将对运行此脚本时可能遇到的典型错误进行说明。
- 修改 desc = arcpy.da.Describe("bike_routes.shp") 行,将下划线字符从 bike_routes 中移除。
desc = arcpy.da.Describe("bikeroutes.shp")
- 保存并运行脚本。
IDLE Shell 显示一条错误消息:
ValueError: Object: Error in accessing describe
该错误表示 da.Describe() 函数存在问题。 此错误的原因是要素类的名称拼写错误,因此无法找到要素类。 如果您遇到此错误,请再次检查名称是否正确。 另一个可能的错误是未正确设置工作空间,因此请确保同时检查所使用的工作空间路径。
注:
除 da.Describe() 之外,您也可以使用常规的 ArcPy 函数 Describe() 检查 GIS 数据集的属性。 其语法与 da.Describe() 略有不同。Describe() 函数会返回 Describe 对象,您可以使用此对象检查其属性。 - 在 IDLE 编辑器窗口中,更改代码行以改正要素类名称。
desc = arcpy.da.Describe("bike_routes.shp")
- 在 print(f'baseName: 行后,添加以下行:
print(f'extension: {desc["extension"]}') print(f'dataType: {desc["dataType"]}') print(f'shapeType: {desc["shapeType"]}')
- 保存并运行脚本。
将打印输入数据集的基本名称、文件扩展名、数据类型和几何类型。 在目录窗格中很容易看到 bike_routes.shp 为折线 shapefile,但是现在,您可以在 Python 脚本中访问这些属性。
虽然还有很多属性可以访问,但是此操作为理解每个数据集提供了一个良好的开端。 您可以在 ArcGIS Pro 帮助页面的 ArcPy 文档部分查看完整的属性列表。
帮助页面中有许多不同的属性,并且这些属性组织在属性组中。 上方链接中的 Describe 属性组包含所有数据集的一些常规属性,包括 baseName、extension 和 datatype。 此外,还有适用于特定数据集类型的属性组。 例如,FeatureClass 属性组包含先前的代码示例中使用的 shapeType 属性。 并非所有数据集都具有此属性,因为它们可能不包含任何几何。 导航帮助页面时,可能难以找到某些属性。 例如,extent 属性位于 Dataset 属性组中。 属性组仅与帮助页面的组织方式有关,对代码没有影响。
接下来,您将替换对数据集的引用,以使用脚本来探索其他数据集。
描述其他数据集
现在,您已经获得了描述 bike_routes.shp 数据集的脚本,您将对其进行修改以描述其他数据。
- 修改 desc = arcpy.da.Describe("bike_routes.shp") 行,将 bike_routes.shp 替换为 watersheds.shp。
desc = arcpy.da.Describe("watersheds.shp")
- 保存并运行脚本。
- 修改 desc = arcpy.da.Describe("bike_routes.shp") 行,将 watersheds.shp 替换为 bike_racks.csv。
desc = arcpy.da.Describe("bike_racks.csv")
- 保存并运行脚本。
IDLE Shell 显示一条错误消息。
KeyError: 'shapeType'
这意味着使用字典时出现错误,因为字典的键 shapeType 不存在。 当您考虑 shapeType 的含义时,会发现这是合理的。 文本文件没有几何,因此无法分类为点、折线或面。 字典中没有此属性,因为属性对于 CSV 文件而言无意义。
da.Describe() 返回的字典仅包含对于给定数据类型有意义的键和值。
您可以通过执行检查来防止发生此错误。
- 在脚本的 print(f'dataType: {desc["dataType"]}') 行后单击,然后按 Enter 键以添加新行。
- 在 print(f'dataType: 行后,添加以下行:
if "shapeType" in desc:
该行包含一个 if 语句。 If 语句行包含一个测试,在本例中,用于确定字符串 "shapeType" 是否在字典 desc 中。 在测试后,if 语句后跟一个冒号。 下一行是根据条件运行的代码块的第一行,可在测试评估为 True 的条件下运行。 代码块中的行必须缩进以向 Python 表明它们是一个整体,且仅在测试为真时才会运行。
- 单击最后一行的开头并添加四个空格以缩进该行。
最后两行代码如下所示:
if "shapeType" in desc: print(f'shapeType: {desc["shapeType"]}')
- 保存并运行脚本。
CSV 文件的结果正确打印。 结果打印了前三个属性,然后 if 语句测试了字典是否包含 "shapeType",因为不包含,所以最后一行未运行。
如何可以看到哪些属性适用于给定数据集?
您可以通过打印整个字典来查看属性。
接下来,您将查看如何打印属性。
打印数据集的所有属性
您已经了解了如何打印字典的特定键和值,以及如何测试特定键是否在字典中。 接下来,您将查看如何打印整个字典。
- 选择脚本的最后五行。
其中包括打印前三个属性的行,以及 if 语句和最后的打印行。
- 选择代码行后,单击格式,然后单击注释掉区域。
所选行前面现在有两个井号。 对于 #,前导符号 Python 会将一行转换为注释,因此在代码运行时不会运行这些行。
您也可以通过在每行的开头输入井号来完成此操作,但 IDLE 中的菜单选项允许您通过一个步骤对多行执行操作。
要反向执行操作,您可以选择代码行,然后从格式菜单中选择取消注释区域。
- 在脚本底部添加一行新代码并移除缩进。
- 添加以下行:
for k, v in desc.items(): print(f"{k}: {v}")
两个新代码行的第一行会开始 for 循环。 For 循环会接收一组输入和一个缩进代码块,并针对每个输入运行代码块。 在这种情况下,for 循环在 desc 字典上调用 items 方法,从而在键值对中遍历。 有关在字典中循环的详细信息,请参阅 Python 文档。
两行代码中的第二行已缩进。 该行是 for 循环代码块的唯一一行代码。 每次循环运行时,该行都会打印一个格式化字符串,其中包含用冒号分隔的 k 和 v 变量的值(键和值)。
- 保存并运行脚本。
代码将遍历字典中的所有项目并打印键和值。
您可以通过打印字典查看给定数据类型的属性。
接下来,您将查看地理数据库中的一些元素。
描述地理数据库要素类
现在您已经了解了如何检查基于文件的 shapefile 和 CSV 表的属性,您将使用 Python 检查地理数据库中项目的属性。 您将使用之前使用的一组打印语句,而不是列出所有属性。
- 选择之前设置为注释的五行代码,单击格式,然后单击取消注释。
- 注释掉用于遍历字典的最后两行代码。
- 修改 mypath = "C:/Lessons/PythonDesc" 行以添加 /DC.gdb。
mypath = "C:/Lessons/PythonDesc/DC.gdb"
- 修改 desc = arcpy.da.Describe("bike_racks.csv") 行以描述 boundary 要素类。
desc = arcpy.da.Describe("boundary")
地理数据库中的元素没有文件扩展名,因此仅基于其数据类型进行区分。
- 保存并运行脚本。
第二个属性是文件扩展名。 虽然此属性是字典中的有效键,但值为空。 由于空文件扩展名对于地理数据库元素很常见,因此您可以添加另一个 if 语句以仅在存在扩展名时打印扩展名行。
- 将 print(f'extension: {desc["extension"]}') 行替换为以下两行:
if desc["extension"] != "": print(f'extension: {desc["extension"]}')
比较运算符 != 表示“不等于”。 Python 中有效的比较运算符包含 ==(等于)、!=(不等于)、<(小于)、<=(小于或等于)、>(大于)和 >=(大于或等于)。 请注意,=! 和 <> 似乎也应该有效果,但它们不是有效的比较运算符并且会产生语法错误。
两行代码中的第一行用于检查与 "extension" 键关联的值是否不等于空字符串(两个引号之间没有任何内容)。 如果评估为 True,则运行用于打印包含 extension 键名称及其关联值的格式化字符串的代码行。
- 保存并运行脚本。
代码运行并检查 extension 键是否不具有空值。 因为其确实具有空值,所以测试评估为 False,因此缩进代码块中的行不会运行,代码不会打印该行。 代码将转到代码块外部的下一行并继续执行,打印 dataType 和 shapeType。
您可以通过更改 da.Describe() 函数中的项目名称以类似的方式浏览地理数据库中的其他元素。
- 修改 desc = arcpy.da.Describe("boundary") 行,将 boundary 替换为 car_share_locations。
desc = arcpy.da.Describe("car_share_locations")
- 保存并运行脚本。
car_share_locations 项目是一个地理数据库表。 其中没有扩展名,也没有 shapeType 条目,因此不会打印这些行。
- 修改 desc = arcpy.da.Describe("car_share_locations") 行以描述 Transportation 项目。
desc = arcpy.da.Describe("Transportation")
- 保存并运行脚本。
Transportation 是地理数据库中的要素数据集。 要素数据集包含共享公共坐标系的数据元素。 要素数据集可用作工作空间。
- 修改 mypath = "C:/Lessons/PythonDesc/DC.gdb" 行以添加 /Transportation。
mypath = "C:/Lessons/PythonDesc/DC.gdb/Transportation"
您现在即可描述要素类和要素数据集中的其他元素。
- 修改 desc = arcpy.da.Describe("Transportation") 行以描述 Traffic 项目。
desc = arcpy.da.Describe("Traffic")
- 保存并运行脚本。
Traffic 是一个网络数据集。 网络数据集用于对交通网络进行建模。 它们通过源要素创建(其中可以包括简单要素(线和点)和转弯要素),并存储源要素的连通性。 执行网络分析时,始终在网络数据集上实现。
da.Describe() 中还可以使用其他数据类型,但您描述的项目涵盖了一些最典型的 GIS 数据集类型。 然而,逐个描述数据集可能十分麻烦。 如果能够创建工作空间中可用的各种数据集的列表,而无需输入其各自的名称,则会很有帮助。
列出工作空间中的文件
处理多个数据集是 Python 脚本中的常见任务。 输入每个单独数据集的名称既麻烦又耗时。 ArcPy 包含多个用于创建数据集清单的函数。 这些函数通常将数据集作为支持进一步处理的 Python 列表返回。
- 您将使用一个新脚本开始操作。
- 在 IDLE 编辑器窗口中,单击文件,然后单击另存为。
当前脚本的文件名为 describe_data.py。 您将使用另存为创建一个新脚本,以继续您的工作,同时将到目前位置完成的工作保留在 describe_data.py 文件中以便将来参考。
- 在另存为对话框上,输入 list_data.py,然后单击保存。
- 在 describe_data 脚本窗口,选择除前三行以外的所有行,然后按 Delete 键。
- 编辑 mypath = 行以从路径中移除 /DC.gdb/Transportation。
mypath = "C:/Lessons/PythonDesc"
此操作将保留教程数据的基本文件夹的路径。
- 在 arcpy.env.workspace 行后,添加以下两行:
files = arcpy.ListFiles() print(files)
这些代码行的第一行将创建一个名为 files 的新变量,并将其设置为等于调用 ListFiles 函数的结果。 函数后跟一个用括号括起来的参数列表。 在本例中,ListFiles() 函数不需要任何输入参数,因此括号为空。
第二行代码用于打印列表。
代码应如下所示:
import arcpy mypath = "C:/Lessons/PythonDesc" arcpy.env.workspace = mypath files = arcpy.ListFiles() print(files)
- 保存并运行脚本。
这是 PythonDesc 文件夹中文件的列表。 Python 列表会用方括号括起来。
ListFiles 函数可以返回当前工作空间内的文件。 这意味着如果没有使用 arcpy.env.workspace 设置工作空间,结果将是一个空列表并且脚本将打印 None。
该函数没有必填参数,它会自动使用当前工作空间。 列出的文件与文件资源管理器中的可见文件十分相似。 有一种例外情况。 地理数据库是文件资源管理器中的文件夹,但是包含在 ListFiles() 的结果中。 因此,DC.gdb 在此处显示为文件,尽管从技术角度而言它是包含文件的文件夹。
应将搜索限制为仅返回特定文件类型。
- 编辑 files = arcpy.ListFiles() 行,以在括号内添加 "*.csv"。
files = arcpy.ListFiles("*.csv")
ListFiles 函数可以接受名为 wildcard 的可选参数,您可通过此参数指定搜索结果必须包含的字符串。 星号表示零或更多未指定的字符,所以此通配符搜索会返回所有包含 .csv 扩展名的文件名。
- 保存并运行脚本。
此脚本将打印匹配结果的列表。 在本例中,是一个单项目列表。
['bike_racks.csv']
这种方法适用于任意数量的文件,是一种以列表形式获取相同文件类型的所有文件并对每个文件执行相同任务的好方法。
您还可以列出其他文件类型,例如 .xlsx、.dbf 等,或者您可以匹配名称字符串的其他部分。 例如,使用通配符字符串 "*bike*" 会返回所有包含 bike 的文件名的列表:['bike_racks.csv', 'bike_routes.dbf', 'bike_routes.prj', 'bike_routes.sbn', 'bike_routes.sbx', 'bike_routes.shp', 'bike_routes.shx']
- 修改 mypath = "C:/Lessons/PythonDesc" 行以包含 DC.gdb
mypath = "C:/Lessons/PythonDesc/DC.gdb"
- 从 ListFiles 函数中移除 "*.csv" 参数。
files = arcpy.ListFiles()
- 保存并运行脚本。
这些文件与您使用文件资源管理器在 DC.gdb 文件夹中看到的文件相同。 ListFiles() 函数不是检查地理数据库内容的实用方法,因为数据集不对应于单个文件。 幸运的是,有一个用于列出要素类的函数。
列出工作空间中的要素类
要素类是最常用的 GIS 数据集类型。 ListFeatureClasses() 函数可以返回当前工作空间中要素类的列表。
- 编辑 mypath = 行以从路径中移除 /DC.gdb。
mypath = "C:/Lessons/PythonDesc"
此操作将保留教程数据的基本文件夹的路径。
- 编辑 files = arcpy.ListFiles() 行以使用 ListFeatureClasses。
files = arcpy.ListFeatureClasses()
代码应如下所示:
import arcpy mypath = "C:/Lessons/PythonDesc" arcpy.env.workspace = mypath files = arcpy.ListFeatureClasses() print(files)
- 保存并运行脚本。
此脚本将打印一个包含两个要素类的列表。
['bike_routes.shp', 'watersheds.shp']
在本例中,要素类为 shapefile。 这有时可能会引起混淆。 术语“要素类”用于描述同类要素的集合,每个要素类具有相同的空间制图表达(例如,点、线或面)和一组共同的属性。 ArcGIS Pro 中两种最常见的要素类类型为 shapefile 和地理数据库要素类。
ListFeatureClasses() 函数适用于 shapefile 和地理数据库要素类,但对于给定工作空间,仅会返回其中一个。 当工作空间为文件夹时,此函数将列出 shapefile。 当工作空间为地理数据库时,此函数将列出地理数据库要素类。
- 编辑 mypath = 行,以将 /DC.gdb 添加到路径。
mypath = "C:/Lessons/PythonDesc/DC.gdb"
此为文件地理数据库的路径。
- 保存并运行脚本。
此脚本将打印三个要素类的列表。
['neighborhoods', 'boundary', 'public_schools']
列表不包含 Transportation 要素数据集中的要素类,因为这是不同的工作空间。
您可以使用通配符过滤 ListFeatureClasses() 的结果。 例如,您可以获取所有以某个字母为开头的要素类。 您还可以使用此函数按照要素类型过滤。 ListFeatureClasses() 函数的语法如下:
ListFeatureClasses ({wild_card}, {feature_type}, {feature_dataset})
可以使用函数的 feature_type 参数基于要素类类型限制结果。
- 编辑 files = arcpy.ListFeatureClasses() 行以使用两个参数 ("", "POINT")。
files = arcpy.ListFeatureClasses("", "POINT")
第一个参数 wild_card 未被使用,但是因为参数有规定的顺序,所以需要跳过此参数。 空字符串 "" 可用作占位符,以指示未使用该参数。 您也可以使用 Python 关键字 None。
您还可以提供按名称引用的参数,在这种情况下,无需遵循原始顺序。 这两种替代方式也可以有效编写此代码行:
files = arcpy.ListFeatureClasses(None, "POINT")
files = arcpy.ListFeatureClasses(feature_type="POINT")
您还可以使用数字符号作为字符串 ("#") 以跳过工具参数。 但是,这不适用于 ArcPy 的非工具函数。
大多数情况下,Python 区分大小写,但 ArcPy 函数中使用的字符串通常不区分大小写。 因此,您也可以在参数中使用 "Point" 或 "point"。
函数可以使用的第三个参数 feature_dataset 未被使用,您可以将其完全省略,因为它位于参数序列的末尾。
- 保存并运行脚本。
此脚本将打印工作空间中的一个点要素类。
['public_schools']
列出表和数据集
您已经列出了文件和要素类。 接下来,您将列出表和要素数据集。
- 编辑 mypath = 行以从路径中移除 /DC.gdb。
mypath = "C:/Lessons/PythonDesc"
此操作将保留教程数据的基本文件夹的路径。
- 将 files = arcpy.ListFeatureClasses(feature_type="POINT") 行编辑为 ListTables()。
files = arcpy.ListTables()
代码应如下所示:
import arcpy mypath = "C:/Lessons/PythonDesc" arcpy.env.workspace = mypath files = arcpy.ListTables() print(files)
- 保存并运行脚本。
此脚本将打印工作空间中两个表的列表。
['gardens.dbf', 'bike_racks.csv']
- 编辑 mypath = 行,以将 /DC.gdb 添加到路径。
mypath = "C:/Lessons/PythonDesc/DC.gdb"
此操作将设置地理数据库的路径。
import arcpy mypath = "C:/Lessons/PythonDesc/DC.gdb" arcpy.env.workspace = mypath files = arcpy.ListTables() print(files)
- 保存并运行脚本。
此脚本将打印包含地理数据库中单个表的列表。
['car_share_locations']
- 将 files = arcpy.ListTables() 行编辑为 ListDatasets()。
files = arcpy.ListDatasets()
import arcpy mypath = "C:/Lessons/PythonDesc/DC.gdb" arcpy.env.workspace = mypath files = arcpy.ListDatasets() print(files)
- 保存并运行脚本。
此脚本将打印包含地理数据库中单个要素数据集的列表。
['Transportation']
- 编辑 mypath = 行,以将 /Transportation 添加到路径。
mypath = "C:/Lessons/PythonDesc/DC.gdb/Transportation"
此操作将设置 Transportation 要素数据集的路径。
import arcpy mypath = "C:/Lessons/PythonDesc/DC.gdb/Transportation" arcpy.env.workspace = mypath files = arcpy.ListDatasets() print(files)
- 保存并运行脚本。
此脚本将打印包含 Transportation 数据集中单个网络数据集的列表。
['traffic']
ListDatasets() 函数适用于各种数据元素。 包括要素数据集、几何网络、网络、宗地结构、栅格目录、拓扑和多种其他元素。
现在您已经了解了如何使用列表函数来创建数据清单,您将使用生成的列表来描述列表的每个元素。
遍历列表
创建数据列表通常是大型工作流中的第一步。 在大多数情况下,您希望对每个数据集执行某种任务。 您将使用 Python for 循环遍历列表。
您将使用一个新脚本开始操作。
- 单击文件,然后单击另存为。
- 将新文件命名为 iterate_data.py。
- 编辑 mypath = 行以从路径中移除 /Transportation。
mypath = "C:/Lessons/PythonDesc/DC.gdb"
- 编辑 files = arcpy.ListDatasets() 行以使用 ListFeatureClasses 函数。
files = arcpy.ListFeatureClasses()
- 将 print(files) 行替换为 for file in files:,然后按 Enter 键。
行尾的冒号表示代码块的开始。 for 循环将遍历列表中的元素,并为每个元素运行代码块中的缩进代码。 当您在一行以冒号结尾的代码后按 Enter 键时,下一行代码会自动缩进。
在每个循环中,都会为临时变量 file 分配一个 files 变量的文件列表中的名称。
- 在缩进的新行处,添加以下内容:
desc = arcpy.da.Describe(file)
da.Describe() 函数将返回包含要素类属性的字典。 将为要素类列表中的每个要素类运行此代码行。
- 按 Enter 键并添加以下内容:
print(desc["baseName"])
此行应缩进四个空格以匹配上一行。 它是 for 循环代码块的一部分,将为列表中的每个要素类运行。
此行将检索并打印使用 baseName 键存储在 desc 字典中的值。
完整代码如下所示:
import arcpy mypath = "C:/Lessons/PythonDesc/DC.gdb" arcpy.env.workspace = mypath files = arcpy.ListFeatureClasses() for file in files: desc = arcpy.da.Describe(file) print(desc["baseName"])
- 保存并运行脚本。
此脚本将在三个新行上打印三个要素类的名称。
neighborhoods boundary public_schools
您将修改代码,以使结果的信息更加丰富。
- 将 print(desc["baseName"]) 行编辑为 name = desc["baseName"]。
此代码行会将名称存储在 name 变量中,而非打印名称。
此行应缩进以匹配代码块中的前一行,使其在循环语句的每次循环中运行。
- 添加以下三行:
data = desc["dataType"] shape = desc["shapeType"] print(f"{name} is a {data} with {shape} geometry")
这些代码会将数据类型和几何值存储在 data 和 shape 变量中。
最后一行将创建并打印一个格式化字符串,三个变量的内容已替换到字符串中。
- 保存并运行脚本。
此脚本将打印三个格式化的字符串:
neighborhoods is a FeatureClass with Polygon geometry boundary is a FeatureClass with Polygon geometry public_schools is a FeatureClass with Point geometry
您列出了地理数据库中的要素类,遍历了列表并打印了每个要素类的相关信息。 接下来,您将添加代码以追踪每种类型的要素类有多少。
追踪要素类类型的数量
您可以检查每个要素类的属性并使用条件逻辑来确定后续操作。 在本部分中,您将使用 if 语句按几何类型计算要素类数量。
- 在 for file in files: 行前插入新行。
- 在 for 循环前添加以下三行:
count_point = 0 count_line = 0 count_poly = 0
这些行可将三个新变量设置为零值。 您将使用这些变量追踪各个要素类的数量。
在 for 循环之前,它们已设置为零值,因此在 for 循环中,您可以根据要素类类型增加其数量。 如果您在 for 循环中定义了变量并将其设置为零,每次循环运行时,您将失去上一次循环中的数据。
- 在 for 循环中,删除最后四行。
- 在 for 循环的 desc = arcpy.da.Describe(file) 后,添加以下行:
if desc["shapeType"] == "Point": count_point += 1
if 应该与 desc 行缩进至同一级别。
if 行将执行检查以确定 desc 字典中存储于 shapeType 键的值是否等于字符串 Point。
在 Python 中,双等号 == 用于检查是否相等,而单个等号用于为变量赋值。
该行后跟一个冒号,因为下一行是新的代码块,所以将进行缩进。
如果语句为假,则不会执行任何处理。 如果语句为真,将运行 if 语句之后代码块。
此代码块会将 count_point 变量中存储的值加一。 当循环运行时,代码会检查要素类列表中的每个项目,以确定其是否是点要素类,如果是,则变量加一。 当循环运行完成时,计数器变量将包含点要素类的计数。
您将再添加两个 if 语句以检查其他几何类型。
- 在最后一个代码行的末尾,按 Enter 键。
新行将与当前代码块中的现有缩进对齐。 但是,您希望下一个 if 语句在之前的 if 语句的缩进级别处对齐。
- 按 Backspace 键。
此操作将调整缩进,以将新行与之前的 if 语句对齐。
- 添加以下代码行:
if desc["shapeType"] == "Polyline": count_line += 1 if desc["shapeType"] == "Polygon": count_poly += 1
您可以使用 Backspace 键调整缩进以将其删除,也可以添加四个空格以增加缩进。
现在,对于文件列表中的每个项目,脚本都将进行描述,描述结果的字典将存储在 desc 变量中,并且将检查存储在 shapeType 键处的数据是否与字符串 Point、Polyline 或 Polygon 匹配。 当匹配时,该形状的计数器变量会增加一。
现在,您将添加一些代码行以打印信息。
- 在脚本末尾处,添加一行代码并按 Backspace 以移除缩进。
- 添加以下代码行:
print(f"Count of Point feature classes: {count_point}") print(f"Count of Polyline feature classes: {count_line}") print(f"Count of Polygon feature classes: {count_poly}")
因为最后三行没有缩进,所以它们不是 for 循环代码块的一部分,这些代码仅在循环完成并且记录了每种形状类型的数量后才运行。
- 保存并运行脚本。
脚本将打印以下三行:
Count of Point feature classes: 1 Count of Polyline feature classes: 0 Count of Polygon feature classes: 2
此脚本显示了一种使用 Python 处理数据的方法。 首先,获取数据列表,然后使用该信息对数据进行某些处理。 此示例仅对要素类进行计数,但类似的脚本可用于其他任务,例如复制所有面要素类或检查所有点要素类的属性。
您已经打印了三种几何的要素类数量。 接下来,您将看到一种可执行同样操作的更加紧凑的方式。
使用要素类型过滤器获取计数
获取工作空间中要素类计数的另一种方法是将 ListFeatureClasses() 函数与要素类型的过滤器配合使用。
- 单击文件,然后单击另存为。
- 将新文件命名为 filter_by_type.py。
- 选择脚本前三行和最后三行之间的代码行,单击格式,然后单击注释掉区域。
- 在注释掉的部分之后、print 行之前添加新行。
- 添加以下代码行:
count_point = len(arcpy.ListFeatureClasses(feature_type="POINT")) count_line = len(arcpy.ListFeatureClasses(feature_type="POLYLINE")) count_poly = len(arcpy.ListFeatureClasses(feature_type="POLYGON"))
这三行以一种新的方式设置 count_point、count_line 和 count_poly 变量。
其中的每一行都使用具有可选 feature_type 参数的 ListFeatureClasses() 函数,而不是将变量设置为零并增加其值。 此函数可创建与过滤器参数匹配的要素类的列表。 len 函数用于确定结果列表的长度,这是该类型的要素类的计数。
- 保存并运行脚本。
脚本将打印以下三行:
Count of Point feature classes: 1 Count of Polyline feature classes: 0 Count of Polygon feature classes: 2
此代码解决方案(不包括注释掉的行)比之前使用 da.Describe() 确定几何类型的方法更短。 但是,使用 da.Describe() 可以检查几何类型以外的属性,例如字段数、空间范围和坐标系。
- 关闭脚本和 IDLE Shell 窗口。
您已经看到了两种用于获取不同类型要素类的计数并将该信息打印到 IDLE Shell 的方法。 接下来,您将查看一个关于如何在脚本中同时使用这些方法的示例,该脚本用于列出和描述工作空间内容并将结果写入文本文件。
将清单信息写入文本文件
虽然打印到交互式窗口可以提供即时反馈,但有时将结果写入文本文件可能更加实用。 已完成的可实现此目标的脚本位于 PythonDesc 文件夹中。
- 在 File Explorer 中,转至用于提取数据的 PythonDesc 文件夹。
- 右键单击 write_inventory.py,然后单击 使用 IDLE 编辑(ArcGIS Pro)。
您将查看脚本,在必要时调整路径,然后运行脚本以查看其运行情况。 为了提高可读性,脚本包含注释行和空行,但是这些内容不会对代码运行造成影响。
此脚本以包含作者、日期和用途的注释为开头。 在脚本中添加此类备注以提醒脚本用途和创建时间是一种很好的做法。 如果您共享脚本,此信息有助于其他用户理解脚本,并使其了解在出现问题时应与谁联系。
脚本中运行的前几行代码用于导入 arcpy 和 os 模块。
import arcpy import os
os 模块可以为您提供通过 Python 访问操作系统级函数的权限。
下一部分用于为路径和工作空间设置一些变量。
#Variables for paths and workspace root = "C:/Lessons/PythonDesc" gdb = "DC.gdb" textfile = "inventory.txt" arcpy.env.workspace = os.path.join (root, gdb) output = os.path.join(root, textfile)
此部分以注释为开头,用于标识这部分代码的作用。 这是编写 Python 代码时的另一种实用做法。
- 如果您将 PythonDesc 提取到 C:/Lessons/PythonDesc 之外的其他位置,请编辑 root = "C:/Lessons/PythonDesc" 行中的路径以指向计算机上文件夹的位置。
无论根数据夹为何,文件地理数据库的名称和文本文件名都可以保持不变,设置 arcpy.env.workspace 的代码行也可以保持不变。 通过对根文件夹路径使用变量,您仅需要在脚本中的一个位置更新路径。 os.path.join() 函数用于根据 root 变量及 gdb 和 textfile 变量创建完整路径。
接下来,将使用 open() 函数创建新的空文本文件并使用 "w" 指定写入模式。 如果已存在具有此名称的文件,则文件会被覆盖。
#Create new textfile to write results f = open(output, "w")
脚本的下一部分使用 ListFeatureClasses() 函数获取三个几何类型的列表。
#Create list of feature classes by geometry type points = arcpy.ListFeatureClasses("", "POINT") lines = arcpy.ListFeatureClasses("", "POLYLINE") polygons = arcpy.ListFeatureClasses("", "POLYGON")
脚本的下一部分使用格式化字符串将上下文信息写入文本文件。 每一行末尾处的 \n 会添加一个用于编写新代码行的转义字符,因此信息将在文本文件中显示为三个单独的行。
f.write(f"Workspace of interest: {arcpy.env.workspace}\n") f.write(f"This workspace contains the following feature classes:\n") f.write(f"Count of Point feature classes: {len(points)}\n")
这些行中的第三行使用 len(points) 在字符串中插入 points 列表的长度,即工作空间中点要素类的数量。
下一行包含检查点要素类列表中是否有项目的 if 语句。 如果其中没有点,则不会执行下一个 f.write 行之前的任何操作。 但是,如果存在点要素类,则运行该行之后的代码块,并且脚本会将新的格式化字符串写入文本文件。
if len(points) != 0: f.write(f"The names of the Point feature classes are:\n") for point in points: desc = arcpy.da.Describe(point) f.write(f'\t{desc["baseName"]}\n') f.write(f"Count of Polyline feature classes: {len(lines)}\n")
接下来,for 将循环处理列表中的每个点要素类。
在循环内部,desc 变量已设置为包含要素类 arcpy.da.Describe 描述的字典。
下一行将写入包含要素类名称的格式化字符串,此名称使用 baseName 键从字典中检索得出。 该行使用 \t 转义字符缩进一个制表符长度,然后会添加一个包含 \n 的新行。 接下来,会对其他所有点要素类重复循环。 当没有更多内容时,f.write 行会运行并将描述折线要素类数量的文本添加到文本文件中,还将使用 \n 开始新行。
本部分的其余内容将以相同的方式报告折线和面要素类。
if len(lines) != 0: f.write(f"The names of the Polyline feature classes are:\n") for line in lines: desc = arcpy.da.Describe(line) f.write(f'\t{desc["baseName"]}\n') f.write(f"Count of Polygon feature classes: {len(polygons)}\n") if len(polygons) != 0: f.write(f"The names of the Polygon feature classes are:\n") for polygon in polygons: desc = arcpy.da.Describe(polygon) f.write(f'\t{desc["baseName"]}\n')
当处理面要素类的循环完成时,下一行代码将关闭文本文件。
f.close()
最后一部分使用 os 模块的 startfile 函数打开报告文本文件。
#Open the resulting output file os.startfile(output)
- 保存并运行脚本。
文本文件将在 Notepad 中打开。
结果将使用文件的 write() 方法写入文本文件。 换行符 \n 用于确保格式化正确,每个结果显示在新的一行上。 制表符 \t 可以缩进要素类的名称,从而提高可读性。 这些特殊字符将使用反斜杠。
您可以通过将 f.write 的实例均替换为 print 来将结果打印至交互式窗口,而不是写入文本文件。 如果您希望在 ArcGIS Pro 中以脚本工具的形式运行脚本,则可以将 f.write 替换为 arcpy.AddMessage 以将信息写入地理处理工具消息。
查看
- Python 代码可用于描述 GIS 数据集的属性,例如数据类型、文件扩展名和几何。
- ArcPy 包含多个用于创建数据集列表的函数。 特定函数可用于创建文件、数据集、表和要素类的列表。
- 通过使用 Python 代码列出和描述数据集,您可以在工作空间中创建详细的 GIS 数据集清单。 然后,您可以决定根据其特征以不同方式处理每个数据集。
- Python 代码可用于将信息写入文本文件。 这对于报告和记录错误十分有用。
您也可能对由 Esri Press 出版的 Paul A.Zandbergen 博士的适用于 ArcGIS Pro 的 Python 脚本和适用于 ArcGIS Pro 的高级 Python 脚本感兴趣。