Acceso a datos utilizando cursores
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 o actualización. Los cursores se utilizan normalmente para leer geometrías existentes y escribir geometrías nuevas.
Cada tipo de cursor es creado por 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 |
En ArcGIS 10.1 se agregó un nuevo módulo de acceso a datos (arcpy.da). Los cursores existentes anteriormente (que aún se listan bajo arcpy) aún son funcionales y válidos; sin embargo, los nuevos cursores arcpy.da incluyen un rendimiento significativamente más rápido. En la mayoría de los casos, la ayuda ilustrará el uso de los cursores arcpy.da. Para obtener más información sobre el modelo de cursor 'clásico', consulte la tabla siguiente.
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 |
Los cursores respetan las selecciones y consultas de definición de vista de capa/tabla. El objeto de cursor solo contiene las filas que utilizaría cualquier herramienta de geoprocesamiento durante una operación.
Se puede navegar a los cursores en la dirección de avance; no permiten retroceder y recuperar filas que ya hayan sido recuperadas. Si una secuencia de comandos necesita pasar varias veces sobre los datos, se puede llamar el método de cursor restablecer.
Los cursores de búsqueda o actualización se pueden recorrer con un bucle For. También se puede obtener acceso a la próxima fila al utilizar de manera explícita el método siguiente 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, la secuencia de comandos debe realizar N llamadas a next. Una llamada a siguiente después de haber recuperado la última fila del conjunto de resultados devuelve una excepciónStoplteration.
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. La ventaja de utilizar una instrucción With es que garantizará el cierre y la liberación de los bloqueos de la base de datos y de la iteración del restablecimiento independientemente de si el cursor finalizó correctamente u ocurrió una excepción.
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 que fueron proporcionados al argumento del cursor field_names. La propiedad campos de un cursor también se puede utilizar para confirmar el orden de los valores de campo.
El objeto de cursor
SearchCursor, UpdateCursor e InsertCursor crean un objeto de cursor que se puede utilizar para recorrer en iteración 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 |
next() |
Recupera la siguiente fila |
reset() | Restablece el cursor a su posición inicial. | |
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 |
|
next() |
Recupera la siguiente fila |
|
reset() | Restablece el cursor a su posición inicial. |
insertRow
Un cursor de inserción se utiliza para crear nuevas filas e insertarlas. Una vez se haya 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 x in range(0,25):
cursor.insertRow([x, 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, pasando 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 rowtype 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 eliminar la fila.
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 a continuación, se obtiene acceso al nombre de estado y conteo de población por medio de la 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('{0} has a population of {1}'.format(row[0], row[1]))
A pesar de que se puede obtener acceso a todos los campos utilizando un asterisco (*), por lo general no es recomendable. Entre más campos se especifican más lento será el desempeño del cursor. Enumerar solamente los campos que espera utilizar mejorará la eficiencia general del cursor.
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 simples requieren un campo de geometría, por lo general (pero no siempre), denominado Forma. El token OID@ se puede utilizar para obtener acceso al campo ObjectID y el token SHAPE@ (el cual devuelve un objeto de geometría) se puede utilizar para tener acceso al campo de geometría de una clase de entidad sin tener conocimiento previo de cuales son los nombres de campo.
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))
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 es mucho más costoso en términos de 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.
- 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 en ArcMap y la vista previa de una tabla en ArcCatalog 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 ArcMap; cambiar el esquema de una tabla en ArcCatalog; o utilizar un cursor de inserción en una clase de entidad en un IDE de Python, tal como PythonWin, 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 sobre el dataset. Si estas funciones crean un cursor correctamente, aplican un bloqueo exclusivo sobre el dataset para que dos secuencias de comandos 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 secuencias de comandos el acceso a un dataset. Se puede liberar un cursor al:
- Incluirlo dentro de una instrucción With, la cual garantizará la liberación de los bloqueos independientemente de si el cursor se completó correctamente o no
- Llamar a reset() en el cursor
- La finalización del cursor
- Eliminar de forma explícita el cursor por medio de la instrucción del de Python
Una sesión de edición en ArcMap 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.
Cursor y campos BLOB
Un 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())