Ein Cursor ist ein Datenzugriffsobjekt, mit dem entweder die Zeilen in einer Tabelle durchlaufen oder neue Zeilen in eine Tabelle eingefügt werden können. Cursor können in drei Formen auftreten: als Such-, Einfüge- oder Aktualisierungs-Cursor. Cursor werden im Allgemeinen dazu verwendet, bestehende Geometrie zu lesen und neue Geometrie zu schreiben.
Jeder Cursor-Typ wird durch eine entsprechende ArcPy-Funktion (SearchCursor, InsertCursor oder UpdateCursor) für eine Tabelle, eine Tabellensicht, eine Feature-Class oder einen Feature-Layer erstellt. Mit einem Such-Cursor können Zeilen abgerufen werden. Mit einem Aktualisierungs-Cursor können Zeilen positionsabhängig aktualisiert und gelöscht werden. Mit einem Einfüge-Cursor können Sie Zeilen in eine Tabelle oder Feature-Class einfügen.
Cursor | Erläuterung |
---|---|
arcpy.da.InsertCursor(in_table, field_names) | Fügt Zeilen ein. |
arcpy.da.SearchCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) | Schreibgeschützter Zugriff |
arcpy.da.UpdateCursor(in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) | Aktualisiert oder löscht Zeilen. |
Cursor | Erläuterung |
---|---|
arcpy.InsertCursor(dataset, {spatial_reference}) | Fügt Zeilen ein. |
arcpy.SearchCursor(dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields}) | Schreibgeschützter Zugriff |
arcpy.UpdateCursor(dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields}) | Aktualisiert oder löscht Zeilen. |
Cursor können nur in Vorwärtsrichtung durchlaufen werden. Das Zurückkehren zu und Abrufen von bereits abgerufenen Zeilen wird nicht unterstützt. Wenn ein Skript die Daten mehrmals durchlaufen muss, kann die Cursor-Methode reset aufgerufen werden.
Such- oder Aktualisierungs-Cursor können mit einer for-Schleife durchlaufen werden. Um auf die nächste Zeile zuzugreifen, können Sie auch die in Python integrierte next-Methode explizit verwenden, um die nächste Zeile zurückzugeben. Wenn Sie die next-Methode eines Cursors verwenden, um alle Zeilen einer Tabelle mit N Zeilen abzurufen, muss das Skript N Aufrufe von next durchführen. Wenn next aufgerufen wird, nachdem die letzte Zeile im Ergebnissatz abgerufen wurde, wird eine StopIteration-Ausnahme zurückgegeben.
import arcpy
cursor = arcpy.da.SearchCursor(fc, ['fieldA', 'fieldB'])
for row in cursor:
print(row)
Such- und Aktualisierungs-Cursor unterstützen auch with-Anweisungen.
import arcpy
with arcpy.da.SearchCursor(fc, ['fieldA', 'fieldB']) as cursor:
for row in cursor:
print(row)
Jede aus einer Tabelle abgerufene Zeile wird als Liste mit Feldwerten zurückgegeben. Die Werte werden in der Reihenfolge zurückgegeben, in der sie im field_names-Argument des Cursors angegeben sind. Mit der fields-Eigenschaft eines Cursors kann auch die Reihenfolge von Feldwerten bestätigt werden.
Cursor-Objekt
Die Funktionen SearchCursor, UpdateCursor und InsertCursor erstellen ein Cursor-Objekt, das zum Durchlaufen der Datensätze verwendet werden kann. Welche Methoden das von den verschiedenen Cursor-Funktionen erstellte Cursor-Objekt aufweist, hängt vom Typ des erstellten Cursors ab.
Im folgenden Diagramm werden die unterstützten Methoden für die einzelnen Cursor-Typen aufgeführt:
Cursor-Typ | Methode | Auswirkung auf Position |
---|---|---|
arcpy.da.SearchCursor | reset() | Setzt den Cursor auf die Anfangsposition zurück. |
arcpy.da.InsertCursor | insertRow() |
Fügt eine Zeile in die Tabelle ein. |
arcpy.da.UpdateCursor |
updateRow() | Aktualisiert die aktuelle Zeile. |
deleteRow() | Entfernt eine Zeile aus der Tabelle. | |
reset() | Setzt den Cursor auf die Anfangsposition zurück. |
insertRow
Ein Einfüge-Cursor wird verwendet, um neue Zeilen zu erstellen und diese einzufügen. Sobald der Cursor erstellt wurde, wird mit der insertRow-Methode eine Liste (oder ein Tupel) mit Werten eingefügt, die die neue Zeile bilden. Jedem Feld in der Tabelle, das nicht im Cursor enthalten ist, wird der Standardwert des Feldes zugewiesen.
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
Mit der updateRow-Methode kann die Zeile an der aktuellen Position eines Aktualisierungs-Cursors aktualisiert werden. Nachdem eine Zeile aus dem Cursor-Objekt zurückgegeben wurde, können Sie die Zeile wie gewünscht ändern und updateRow aufrufen, um die geänderte Zeile zu übergeben.
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
Mit der deleteRow-Methode kann die Zeile an der aktuellen Position eines Aktualisierungs-Cursors gelöscht werden. Sie rufen nach dem Abrufen der Zeile deleteRow für den Cursor auf, um die Zeile zu löschen.
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()
Zugreifen auf und Festlegen von Feldwerten
Für jeden Cursor sind die verwendeten Felder in einer Liste (oder einem Tupel) mit Feldnamen angegeben. Eine Zeile wird vom Cursor als Liste mit Feldwerten zurückgegeben, die einer Indexposition entsprechen.
Im nachfolgenden Beispiel erfolgt der Zugriff auf den Bundesstaat und die Bevölkerungsanzahl anhand der Position.
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]))
Token können auch als Verknüpfungen anstelle der Feldnamen verwendet werden. Alle Tabellen enthalten ein ObjectID-Feld, das abhängig vom Datentyp unterschiedliche Namen haben kann. Für Simple-Feature-Classes ist ein Geometriefeld erforderlich, in der Regel (aber nicht immer) Shape genannt. Der OID@-Token kann verwendet werden, um auf das ObjectID-Feld zuzugreifen, und der SHAPE@-Token (der ein Geometrieobjekt zurückgibt) kann verwendet werden, um auf das Geometriefeld einer Feature-Class zuzugreifen, wobei nicht bekannt sein muss, wie die Feldnamen lauten.
Such-Cursor für Multipoint-Feature-Class
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))
Zusätzliche Geometrie-Token können verwendet werden, um auf bestimmte Geometrieinformationen zuzugreifen. Der Zugriff auf die vollständige Geometrie ist zeitaufwendiger. Wenn Sie nur bestimmte Eigenschaften der Geometrie benötigen, stellen Sie mithilfe von Token Verknüpfungen bereit, um auf Geometrieeigenschaften zuzugreifen. Zum Beispiel gibt SHAPE@XY ein Tupel von XY-Koordinaten zurück, die den Schwerpunkt des Features darstellen.
Cursor und Sperren
Einfüge- und Aktualisierungs-Cursor berücksichtigen Tabellensperren, die von ArcGIS-Anwendungen festgelegt werden. Sperren verhindern, dass eine Tabelle zu einem bestimmten Zeitpunkt von mehreren Prozessen gleichzeitig geändert wird. Es gibt zwei Typen von Sperren: freigegebene Sperren und exklusive Sperren.
- Eine freigegebene Sperre wird bei jedem Zugriff auf eine Tabelle oder ein Dataset gesetzt. Für eine Tabelle können mehrere freigegebene Sperren vorliegen. Wenn eine freigegebene Sperre vorliegt, sind jedoch keine exklusiven Sperren zulässig. Das Anzeigen einer Feature-Class in ArcMap und die Vorschau einer Tabelle in ArcCatalog sind Beispiele für Situationen, in denen eine freigegebene Sperre gesetzt wird.
- Exklusive Sperren werden gesetzt, wenn Änderungen an einer Tabelle oder Feature-Class vorgenommen werden. Das Bearbeiten und Speichern einer Feature-Class in ArcMap, das Ändern eines Tabellenschemas in ArcCatalog oder das Verwenden eines Einfüge-Cursors für eine Feature-Class in einer Python-IDE, z. B. PythonWin, sind Beispiele für Situationen, in denen von ArcGIS eine exklusive Sperre gesetzt wird.
Aktualisierungs- und Einfüge-Cursor können für eine Tabelle oder eine Feature-Class nur erstellt werden, wenn für das betreffende Dataset keine exklusive Sperre vorliegt. Die Funktionen UpdateCursor oder InsertCursor schlagen aufgrund einer exklusiven Sperre des Datasets fehl. Wenn mit diesen Funktionen erfolgreich ein Cursor erstellt wird, wird eine exklusive Sperre für das Dataset festgesetzt, sodass immer nur ein Skript Aktualisierungs- oder Einfüge-Cursor für dasselbe Dataset erstellen kann.
In Python bleibt die Sperre erhalten, bis der Cursor freigegeben wird. Andernfalls werden alle anderen Anwendungen und Skripte unnötigerweise am Zugriff auf das betreffende Dataset gehindert. Ein Cursor kann wie folgt freigegeben werden:
- Durch Verwenden des Cursors in einer with-Anweisung, die die Aufhebung von Sperren unabhängig davon garantiert, ob der Cursor erfolgreich abgeschlossen wird
- Durch Aufrufen von reset() für den Cursor
- Durch den Abschluss des Cursors
- Durch das explizite Löschen des Cursors mit der del-Anweisung von Python
In einer Editiersitzung in ArcMap wird eine freigegebene Sperre für Daten gesetzt. Beim Speichern der Änderungen wird eine exklusive Sperre gesetzt. Ein Dataset kann nicht bearbeitet werden, wenn bereits eine exklusive Sperre vorliegt.
Cursor und BLOB-Felder
Bei einem BLOB (Binary Large Object) handelt es sich um Daten, die als lange Abfolge von binären Zahlen gespeichert sind. In ArcGIS werden Annotation und Bemaßungen als BLOBs gespeichert. In Feldern dieses Typs können auch Objekte wie Bilder, Multimedia-Komponenten oder Programmcode gespeichert werden. Sie können einen Cursor verwenden, um den Inhalt eines BLOB-Feldes zu laden oder anzuzeigen.
In Python können in BLOB-Feldern Zeichenfolgen, bytearray und memoryviews eingegeben werden. Beim Lesen von BLOB-Feldern wird ein memoryview-Objekt zurückgegeben.
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())