Доступ к данным с помощью курсоров
Курсор – это объект доступа к данным, который может использоваться как для итерации набора строк в таблице, так и для вставки новых строк в таблицу. Курсоры могут быть трех форм: поиска, вставки или обновления. Как правило, курсоры используются для считывания существующей геометрии и записи новых геометрий.
Каждый тип курсора создан соответствующей функцией 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 добавлен модуль доступа к новым данным (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-строками, скрипт должен выполнить n-C1316вызовов next. Вызов 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() курсора
- Завершение работы курсора
- Непосредственное удаление курсора с помощью выражения del Python
На сеансе редактирования в ArcMap применяет общую блокировку данных во время сеанса. Эксклюзивная блокировка применяется при сохранении изменений. Если уже существует эксклюзивная блокировка, то набор данных не является редактируемым.
Курсор и поля типа BLOB
Большой двоичный объект (BLOB) представляет собой некоторую часть данных, хранимую в виде длинной последовательности двоичных чисел. ArcGIS хранит в виде больших двоичных объектов (BLOB) аннотации и объекты-размеры (dimension), а также такие элементы, как изображения и мультимедиа. Курсор можно использовать для загрузки или просмотра содержимого поля 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())