使用arcpy在列表中加载要素类:SearchCursor的奇怪行为

out*_*ile 4 python geometry arcpy

使用arcpy,我的目的是在列表中存储要素类以供进一步处理.每行都是一个{'field name': value}包含几何图形的字典.

实现此任务的最pythonic方法应该是使用list comprehension:

fc = '/path/to/fc'
fields = [f.name for f in arcpy.ListFields(fc)]   # get field list
features = [[row.getValue(f) for f in fields] for row in arcpy.SearchCursor(fc)]
Run Code Online (Sandbox Code Playgroud)

此方法适用于数据,但列表中的几何图形都相同(在fc中检索的最后几何图形).SearchCursor的这种行为已经在StackOverflow上发表了评论.

我尝试了另一种方法:

fc = '/path/to/fc'
shape_field = arcpy.Describe(fc).shapeFieldName

# load geometry in a list
geom = arcpy.Geometry()
feat = [{shape_field: f} for f in arcpy.CopyFeatures_management(fc, geom)] # slow

# load data in a list
fields = [f.name for f in arcpy.ListFields(fc)]
data = [dict([(f, row.getValue(f)) for f in fields if f != shape_field]) for row in arcpy.SearchCursor(fc)] # slow

# merge
merge = zip(feat, data)
merge = [dict([(k, v) for adict in line for (k, v) in adict.items()]) for line in merge] # sorry for that...
Run Code Online (Sandbox Code Playgroud)

它适用于我的数据集但是:

  • 这很慢.
  • 我不确定断言数据和专长的顺序是否相同.

有什么意见吗?

小智 5

如果可能的话,迁移到使用10.1的地方arcpy.da,为游标提供性能更高的API.我已经写了一篇关于让词典回归这个主题的日志帖子.几何图形都是相同的,因为它在内部使用了一个回收光标,所以在10.0中你会想要抓住shape.__geo_interface__并使用AsShape它来回到几何对象.

你获得行的顺序是相当随意的:你可以期望它在每个没有 where子句的shapefile中都是相同的,而且几乎就是它,所以你的双遍方法实际上并不可靠.

考虑到这一切,您可以这样做:

def cursor_to_dicts(cursor, field_names):
    for row in cursor:
        row_dict = {}
        for field in field_names:
            val = row.getValue(field)
            row_dict[field] = getattr(val, '__geo_interface__', val)
        yield row_dict

fc = '/path/to/fc'
fields = [f.name for f in arcpy.ListFields(fc)]   # get field list
features = list(cursor_to_dicts(arcpy.SearchCursor(fc), fields))
Run Code Online (Sandbox Code Playgroud)

魔术就是getattr()召唤 - 尝试抓住value.__geo_interface__它是否存在,否则只是默认value.

由于这个问题一般不是关于Python语言,而是一个arcpy特定于GIS 的API(),你可能最好在将来在gis.stackexchange上询问这样的事情.