使用游标访问数据
游标是一种数据访问对象,可用于在表中迭代一组行或者向表中插入新行。游标有三种形式:搜索、插入或更新。游标通常用于读取现有几何和写入新几何。
每种类型的游标均由对应的 ArcPy 函数(SearchCursor、InsertCursor 或 UpdateCursor)针对表、表视图、要素类或要素图层进行创建。搜索游标可用于检索行。更新游标可用于根据位置更新和删除行,而插入游标可用于向表或要素类中插入行。
游标 |
说明 |
---|---|
arcpy.da.InsertCursor(in_table, field_names) |
插入行 |
arcpy.da.SearchCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) |
只读访问 |
arcpy.da.UpdateCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) |
更新或删除行 |
ArcGIS 10.1 添加了一个新的数据访问模块 (arcpy.da)。先前已存在的游标(仍列在 arcpy 下)的功能仍可正常使用并且有效;不过,新的 arcpy.da 游标的性能要快得多。大多数情况下,帮助中会对 arcpy.da 游标的使用进行说明。有关“典型”游标模型的详细信息,请参阅下表。
游标 |
说明 |
---|---|
arcpy.InsertCursor(dataset, {spatial_reference}) |
插入行 |
arcpy.SearchCursor(dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields}) |
只读访问 |
arcpy.UpdateCursor(dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields}) |
更新或删除行 |
游标遵循图层/表格视图定义查询和选择。游标对象仅包含任一地理处理工具在操作期间将使用到的行。
游标只能向前导航;它们不支持备份和检索已经检索过的行。如果脚本需要多次遍历数据,则可能会调用游标的 reset 方法。
可用 For 循环对搜索或更新游标进行迭代。同样,可通过明确使用游标的 next 方法返回下一行以访问。如果要使用游标的 next 方法来检索行数为 N 的表中的所有行,脚本必须调用 next N 次。在检索完结果集中的最后一行后调用 next 将返回 StopIteration 异常。
import arcpy
cursor = arcpy.da.SearchCursor(fc, ['fieldA', 'fieldB'])
for row in cursor:
print(row)
搜索和更新游标同样支持 With 语句。使用 With 语句的好处是:无论游标成功完成还是出现异常,都会确保数据库锁以及重置迭代的关闭和释放。
import arcpy
with arcpy.da.SearchCursor(fc, ['fieldA', 'fieldB']) as cursor:
for row in cursor:
print(row)
从表中检索的每一行都会作为一组字段值而返回。会按照提供给游标的 field_names 参数的相同顺序返回这些值。游标的 fields 属性也可用于确定字段值的顺序。
游标对象
SearchCursor、UpdateCursor 和 InsertCursor 能够创建可用于遍历记录的游标对象。由不同游标函数创建的游标对象的方法不同,具体取决于创建的游标类型。
下图显示各游标类型所支持的方法:
游标类型 |
方法 |
对位置的影响 |
---|---|---|
arcpy.da.SearchCursor |
next() |
检索下一行 |
reset() | 将游标重置回起始位置 | |
arcpy.da.InsertCursor |
insertRow() |
向表中插入一行 |
arcpy.da.UpdateCursor |
updateRow() |
更新当前行 |
deleteRow() |
从表中删除行 | |
next() |
检索下一行 | |
reset() | 将游标重置回起始位置 |
insertRow
插入游标用于创建新行并插入它们。创建游标后,insertRow 方法用于插入一组值,这些值会组成新行。包含在表中但不包含在游标中的任何字段都将被分配字段的默认值。
import arcpy
# Create insert cursor for table
#
cursor = arcpy.da.InsertCursor("c:/base/data.gdb/roads_lut",
["roadID", "distance"])
# Create 25 new rows. Set the initial row ID and distance values
#
for x in range(0,25):
cursor.insertRow([x, 100])
updateRow
updateRow 方法用于对更新游标当前所在位置的行进行更新。从游标对象返回行后,可以根据需要对行进行修改,然后调用 updateRow 传入修改后的行。
import arcpy
# Create update cursor for feature class
#
with arcpy.da.UpdateCursor("c:/base/data.gdb/roads",
["roadtype", "distance"]) as cursor:
for row in cursor:
# Update the values in the distance field by multiplying
# the rowtype by 100. Road type is either 1, 2, 3 or 4.
#
row[1] = row[0] * 100
cursor.updateRow(row)
deleteRow
deleteRow 方法用于删除更新游标当前所在位置的行。提取行后,可在游标上调用 deleteRow 来删除行。
import arcpy
# Create update cursor for feature class
#
with arcpy.da.UpdateCursor("c:/base/data.gdb/roads",
["roadtype"]) as cursor:
# Delete all rows that have a roads type of 4
#
for row in cursor:
if row[0] == 4:
cursor.deleteRow()
访问和设置字段值
对于每个游标来说,使用的字段均由一组字段名称提供。当从游标中返回行时,是以对应于索引位置的一组字段值的形式返回的。
在下例中,州名和人口计数由位置进行访问。
import arcpy
fc = "c:/base/data.gdb/USA/States"
# Use SearchCursor to access state name and the population count
#
with arcpy.da.SearchCursor(fc, ['STATE_NAME', 'POP2000']) as cursor:
for row in cursor:
# Access and print the row values by index position.
# state name: row[0]
# population: row[1]
#
print('{0} has a population of {1}'.format(row[0], row[1]))
尽管使用星号 (*) 可访问所有字段,但通常不建议这样做。指定的字段越多,游标执行速度越慢。只列出要使用的字段会改善游标整体效率。
令牌同样可以用作快捷键来替代字段名称。所有表都包含 ObjectID 字段,该字段根据数据类型可能具有许多不同名称。简单的要素类需要几何字段,通常(但不总是)名为 Shape。OID@ 令牌可用于访问 ObjectID 字段,而 SHAPE@ 令牌(返回几何对象)可用于访问要素类几何字段,而无需提前了解字段名称是什么。
import arcpy
infc = arcpy.GetParameterAsText(0)
# Enter for loop for each feature
#
for row in arcpy.da.SearchCursor(infc, ["OID@", "SHAPE@"]):
# Print the current multipoint's ID
#
print("Feature {0}:".format(row[0]))
# For each point in the multipoint feature,
# print the x,y coordinates
for pnt in row[1]:
print("{0}, {1}".format(pnt.X, pnt.Y))
附加几何令牌可用于访问特定几何信息。访问完整几何更加耗时。如果只需要几何的某些特定属性,可使用令牌来提供快捷方式从而访问几何属性。例如,SHAPE@XY 会返回一组代表要素质心的 x,y 坐标。
游标和锁定
插入和更新游标遵循由 ArcGIS 应用程序设置的表锁。锁能够防止多个进程同时更改同一个表。有两种锁的类型:共享和排它。
- 只要访问表或数据集就会应用共享锁。同一表中可以存在多个共享锁,但存在共享锁时,将不允许存在排它锁。应用共享锁的示例包括:在 ArcMap 中显示要素类时以及在 ArcCatalog 中预览表时。
- 对表或要素类进行更改时,将应用排它锁。在 ArcGIS 中应用排它锁的示例包括:在 ArcMap 中编辑和保存要素类时;在 ArcCatalog 中更改表的方案时;或者在 Python IDE(例如 PythonWin)中在要素类上使用插入游标时。
如果数据集上存在排它锁,则无法为表或要素类创建更新和插入游标。UpdateCursor 或 InsertCursor 函数会因数据集上存在排它锁而失败。如果这些函数成功地创建了游标,它们将在数据集上应用排它锁,从而使两个脚本无法在同一数据集上创建更新和插入游标。
在 Python 中,在游标释放前保持锁定状态。否则,将会阻止所有其他应用程序或脚本访问数据集,而这是毫无必要的。释放游标的方法为:
- 包括 With 语句内部的游标,这会确保无论游标是否成功完成,都会释放锁
- 调用游标上的 reset()
- 游标的完成
- 使用 Python 的 del 语句明确删除游标
ArcMap 中的编辑会话将在其会话期间对数据应用共享锁。保存编辑内容时将应用排它锁。已经存在排它锁时,数据集是不可编辑的。
游标和 blob 字段
BLOB 是一种存储为长度较长的一系列二进制数的数据。ArcGIS 会将注记和尺寸存储为 BLOB,图像、多媒体或编码的位等项也可存储在此类型的字段中。可使用游标来加载或查看 BLOB 字段的内容。
在 Python 中,BLOB 字段可接受字符串 bytearray 和 memoryviews。当读取 BLOB 字段时,返回 memoryview 对象。
import arcpy
data = open("c:/images/image1.png", "rb").read()
ic = arcpy.da.InsertCursor("c:/data/fgdb.gdb/fc", ['imageblob'])
ic.insertRow([data])
import arcpy
sc = arcpy.da.SearchCursor("c:/data/fgdb.gdb/fc", ["imageblob"])
memview = sc.next()[0]
open("c:/images/image1_copy.png", "wb").write(memview.tobytes())