Un cursor es un objeto de acceso a datos que se puede utilizar para recorrer el conjunto de filas de una tabla o insertar nuevas filas en una tabla. Los cursores tienen tres formas: búsqueda, inserción y actualización. Los cursores se utilizan normalmente para leer geometrías existentes y escribir geometrías nuevas.
Cada tipo de cursor se crea con una función de ArcPy (SearchCursor, InsertCursor o UpdateCursor) en una tabla, vista de tabla, clase de entidad o capa de entidades. Un cursor de búsqueda se puede utilizar para recuperar filas. Un cursor de actualización se puede utilizar para actualizar y eliminar filas en función de la posición, mientras que un cursor de inserción se utiliza para insertar filas en una tabla o una clase de entidad.
Cursor | Explicación |
---|---|
arcpy.da.InsertCursor(in_table, field_names) | Inserta filas |
arcpy.da.SearchCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) | Acceso de solo lectura |
arcpy.da.UpdateCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) | Actualiza o elimina filas |
Cursor | Explicación |
---|---|
arcpy.InsertCursor(dataset, {spatial_reference}) | Inserta filas |
arcpy.SearchCursor(dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields}) | Acceso de solo lectura |
arcpy.UpdateCursor(dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields}) | Actualiza o elimina filas |
Se puede navegar a los cursores en la dirección de avance; no permiten retroceder y recuperar filas que ya hayan sido recuperadas. Si es necesario realizar varias pasadas de un script con los datos, se puede invocar el método de cursor reset.
Los cursores de búsqueda o de actualización se pueden recorrer en un bucle for. También se puede obtener acceso a la próxima fila al utilizar de manera explícita el método next del cursor para devolver la siguiente fila. Cuando se utiliza el método next en un cursor para recuperar todas las filas de una tabla que contiene N filas, el script debe realizar N llamadas a next. Una llamada a next después de haber recuperado la última fila del conjunto de resultados devuelve una excepción StopIteration.
import arcpy
cursor = arcpy.da.SearchCursor(fc, ['fieldA', 'fieldB'])
for row in cursor:
print(row)
Los cursores de búsqueda y actualización también son compatibles con las instrucciones with.
import arcpy
with arcpy.da.SearchCursor(fc, ['fieldA', 'fieldB']) as cursor:
for row in cursor:
print(row)
Cada fila recuperada en una tabla se devolverá como una lista de valores de campo. Los valores se devolverán en el mismo orden en que se proporcionaron al argumento field_names del cursor. La propiedad fields de un cursor también se puede utilizar para confirmar el orden de los valores de campo.
Objeto de cursor
SearchCursor, UpdateCursor y InsertCursor crean un objeto de cursor que se puede usar para realizar iteraciones por los registros. Los métodos del objeto de cursor creados por las diversas funciones de cursor varían, dependiendo del tipo de cursor creado.
El siguiente gráfico muestra los métodos admitidos por cada tipo de cursor:
Tipo de cursor | Método | Efecto sobre la posición |
---|---|---|
arcpy.da.SearchCursor | reset() | Restablece la posición inicial del cursor. |
arcpy.da.InsertCursor | insertRow() | Inserta una fila en la tabla |
arcpy.da.UpdateCursor | updateRow() | Actualiza la fila actual |
deleteRow() | Quita la fila de la tabla | |
reset() | Restablece la posición inicial del cursor. |
insertRow
Un cursor de inserción se utiliza para crear filas e insertarlas. Una vez que se ha creado el cursor, el método insertRow se utiliza para insertar una lista (o tupla) de valores que formarán la nueva fila. Cualquier campo en la tabla que no se incluya en el cursor se asignará al valor predeterminado del campo.
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 i in range(0,25):
cursor.insertRow([i, 100])
updateRow
El método updateRow se utiliza para actualizar la fila en la posición actual de un cursor de actualización. Después de devolver una fila del objeto de cursor, puede modificar la fila como sea necesario y llamar a updateRow para transferir la fila modificada.
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 roadtype by 100. Road type is either 1, 2, 3 or 4.
row[1] = row[0] * 100
cursor.updateRow(row)
deleteRow
El método deleteRow se utiliza para eliminar la fila de la posición actual de un cursor de actualización. Después de obtener la fila, llame a deleteRow en el cursor para eliminarla.
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()
Acceso y configuración de los valores de campo
Para cada cursor, los campos utilizados se obtienen de una lista (o tupla) de nombres de campo. Cuando el cursor devuelve una fila, la devuelve como una lista de valores de campo que corresponden a una posición del índice.
En el ejemplo siguiente, se obtiene acceso al nombre de estado y al recuento de población por posición.
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('{} has a population of {}'.format(row[0], row[1]))
Los tokens también pueden utilizarse como accesos directos en lugar de nombres de campo. Todas las tablas incluyen un campo ObjectID que puede tener muchos nombres diferentes dependiendo del tipo de datos. Las clases de entidad simple requieren un campo de geometría, por lo general (pero no siempre) denominado Shape. El token OID@ se puede utilizar para obtener acceso al campo ObjectID y el token SHAPE@ (que devuelve un objeto de geometría) se puede utilizar para tener acceso al campo de geometría de una clase de entidad sin saber previamente los nombres de campo.
Buscar cursor en una clase de entidad multipunto
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 {}:".format(row[0]))
# For each point in the multipoint feature,
# print the x,y coordinates
for pnt in row[1]:
print("{}, {}".format(pnt.X, pnt.Y))
Los tokens de geometría adicionales se pueden utilizar para obtener acceso a información de geometría específica. Acceder a la geometría completa lleva más tiempo. Si solo necesita propiedades específicas de la geometría, utilice tokens para proporcionar accesos directos a las propiedades de geometría. Por ejemplo, SHAPE@XY devolverá una tupla de las coordenadas x,y que representan el centroide de la entidad.
Cursores y bloqueo
Los cursores de inserción y actualización respetan los bloqueos de tabla establecidos por aplicaciones ArcGIS. Los bloqueos evitan que varios procesos cambien la misma tabla al mismo tiempo. Hay dos tipos de bloqueos: compartidos y exclusivos, y se describen a continuación:
- Un bloqueo compartido se aplica cada vez que se tiene acceso a una tabla o a un dataset. Pueden existir varios bloqueos compartidos para una tabla, pero no se permite ningún bloqueo exclusivo si existe un bloqueo compartido. La visualización de una clase de entidad y la vista previa de una tabla son ejemplos de cuándo se aplicaría un bloqueo compartido.
- Los bloqueos exclusivos se aplican cuando se hace algún cambio en una tabla o clase de entidad. Editar y guardar una clase de entidad en un mapa, cambiar el esquema de una tabla, o utilizar un cursor de inserción en una clase de entidad en un IDE de Python son ejemplos de cuándo aplica ArcGIS un bloqueo exclusivo.
No se puede crear cursores de actualización e inserción para una tabla o clase de entidad si existe un bloqueo exclusivo para ese dataset. Las funciones UpdateCursor o InsertCursor producen un error debido a un bloqueo exclusivo del dataset. Si estas funciones crean un cursor correctamente, aplican un bloqueo exclusivo sobre el dataset para que dos scripts no puedan crear un cursor de actualización o inserción en el mismo dataset.
En Python, el bloqueo persiste hasta que se libera el cursor. De lo contrario, se podría impedir a todas las demás aplicaciones o scripts el acceso a un dataset. Un cursor se puede liberar mediante una de las siguientes acciones:
- Incluir el cursor dentro de una instrucción with, que garantizará la liberación de los bloqueos con independencia de si el cursor se completó correctamente o no.
- Llamar a reset en el cursor.
- El cursor se completa correctamente.
- Eliminar de forma explícita el cursor por medio de la instrucción del de Python.
Una sesión de edición aplica un bloqueo compartido a los datos durante la sesión de edición. Cuando se guardan las ediciones se aplica un bloqueo exclusivo. Un dataset no es editable si ya existe un bloqueo exclusivo.
Cursores y campos BLOB
Los objetos binarios grandes (BLOB) son datos almacenados como una secuencia larga de números binarios. En ArcGIS, las anotaciones y dimensiones se almacenan como BLOB y los elementos, como imágenes, multimedia o bits de código, se pueden almacenar en este tipo de campo. Puede utilizar un cursor para cargar o visualizar el contenido de un campo BLOB.
En Python, los campos BLOB pueden aceptar cadenas de caracteres, bytearray y memoryviews. Al leer los campos BLOB, se devuelve un objeto 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())