[FOSSGIS-Talk] kleine Auffälligkeiten beim featureCount()
Thomas Wölk
thomas.woelk at gmail.com
Mo Mai 11 08:55:43 CEST 2026
Drei Phänomene, drei verschiedene Ursachen.
Warum featureCount() der proc_child_lyr -2 liefert:
Das ist kein mysteriöser Wert, sondern ein Sentinel aus dem
Qgis.FeatureCountState-Enum:
# Aus qgis.h (QGIS 3.20+)
enum class FeatureCountState : int {
Uncounted = -2, # Feature count noch nicht berechnet
UnknownCount = -1, # Provider kennt den Count nicht
};
Dein Layer ist also nicht etwa „negativ befüllt“, sondern ungültig – und
der OGR-Provider hat seinen Counter noch im Initialzustand. Die Ursache
steckt in dieser Zeile:
proc_child_lyr = QgsVectorLayer('proc_child', '', 'ogr')
Du übergibst den String-Literal 'proc_child' als URI, nicht die Variable
proc_child mit dem Pfad zum Temp-Output. Ein proc_child_lyr.isValid() würde
hier False liefern. Richtig wäre:
proc_child_lyr = QgsVectorLayer(proc_child, '', 'ogr') # ohne Quotes
Warum Punkt 2 und 3 dann immer noch unterschiedlich sind:
Selbst nach dem Quote-Fix bleiben die beiden Aufrufe konzeptionell
verschieden, und das ist gewollt:
processing.run(..., is_child_algorithm=True)
gibt im OUTPUT-Dict nur einen URI/Pfad-String zurück. Du bist selbst dafür
verantwortlich, daraus einen Layer zu bauen. Dieser Modus ist für die
Verkettung innerhalb von Modellen gedacht, wo nicht jeder Zwischenschritt
als vollwertiges Layer-Objekt instanziiert werden soll.
processing.run(..., is_child_algorithm=False)
(Default) liefert dir direkt ein lebendes QgsMapLayer-Objekt zurück, das
intern bereits über einen QgsProcessingContext aus dem URI gehoben wurde.
Daher funktioniert proc_lyr.featureCount() sofort.
Wenn du Variante 2 sauber haben willst, geh über die offizielle
Helper-Funktion, statt selbst zu basteln:
from qgis.core import QgsProcessingContext, QgsProcessingUtils
context = QgsProcessingContext()
proc_child = processing.run(
'native:extractbyattribute', alg_params,
context=context, is_child_algorithm=True
)['OUTPUT']
proc_child_lyr = QgsProcessingUtils.mapLayerFromString(proc_child, context)
Damit klappt Memory-Output genauso wie File-Output, ohne dass du den
Provider raten musst.
Aktuellen Zustand der GeoPackage-Tabelle abrufen:
Du hast den Grund schon richtig diagnostiziert: Der OGR-Provider cached den
Feature-Count beim Öffnen, und Trigger-Inserts auf SQLite-Ebene gehen daran
vorbei.
Drei Wege, sauber sortiert nach Aufwand:
Variante A – Layer im Speicher refreshen:
log_tbl.dataProvider().reloadData() # ab QGIS 3.20
log_tbl.updateExtents() # optional, für räumliche Indizes
print(log_tbl.featureCount())
reloadData() zwingt den Provider, seinen internen Cache zu verwerfen. In
den meisten Fällen reicht das. Vorsicht: Wenn dein Modell den auslösenden
Layer per QGIS-Edit-Session ändert, feuern die Trigger erst bei
commitChanges(). Vorher ist in der DB nichts zu sehen.
Variante B – über die Provider-Connection direkt SQL absetzen:
from qgis.core import QgsProviderRegistry
md = QgsProviderRegistry.instance().providerMetadata('ogr')
conn = md.createConnection('/pfad/zum/file.gpkg', {})
result = conn.executeSql(
"SELECT COUNT(*) FROM t_sys_log_leitbild WHERE user = 'Horst'"
)
count = result[0][0]
Das ist der providerunabhängige PyQGIS-Weg und umgeht jeden Caching-Layer.
Funktioniert für GPKG, PostGIS, SpatiaLite gleichermassen.
Variante C – sqlite3 direkt:
import sqlite3
with sqlite3.connect('/pfad/zum/file.gpkg') as con:
count = con.execute(
"SELECT COUNT(*) FROM t_sys_log_leitbild WHERE user = ?",
('Horst',)
).fetchone()[0]
Kürzer und für GeoPackage absolut legitim, aber bindet dich an den
konkreten Treiber. Für reine Lese-Counts unproblematisch, fürs Schreiben
würde ich es vermeiden, weil du das GeoPackage-Metadaten-Management umgehst.
Tradeoff: Variante A ist am idiomatischsten, wenn der Log-Layer ohnehin
geladen ist. Variante B ist die robusteste, wenn das Skript auch außerhalb
eines geladenen Projekts läuft (Standalone-Tool, Headless-Processing).
Variante C nur, wenn du sicher bist, dass es immer ein GeoPackage bleibt.
— Thomas
Am 11.05.2026, 08:11:40 schrieb bmarcus via FOSSGIS-Talk-Liste <
fossgis-talk-liste at fossgis.de>:
> Hallo Listenmitglieder,
>
>
>
> ich bin zwar kein blutiger Python Anfänger, aber mit der PyGIS-API tu ich
> mich immer wieder gerne schwer.
>
> Um den Standart-Wert von Eingabeparameter eines QGIS-Modells etwas
> dynamischer zu gestalten, habe ich das Modell als Python-Skript exportiert
> und entsprechend angepasst. Um die Lauffähigkeit des Skripts zu
> gewährleisten, stehen natürlich noch weitere Änderungen an, bei denen ich
> auf ein interessantes, mir unerklärliches Phänomen bei der Bestimmung der
> Objektanzahl gestoßen bin. Nachfolgendes Skriptschnippsel
>
>
>
> log_tbl = QgsProject.instance().mapLayer(
>
> 't_sys_log_leitbild_24ced76d_bd40_43af_a214_35d4ad8b545f'
>
> )
>
> print(f'1. Anzahl Features log: {log_tbl.featureCount()}')
>
>
>
> alg_params = {
>
> 'FIELD': 'user',
>
> 'INPUT': 't_sys_log_leitbild_24ced76d_bd40_43af_a214_35d4ad8b545f',
>
> 'OPERATOR': 0,
>
> 'VALUE': 'Horst'
>
> 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT
>
> }
>
> proc_child = processing.run(
>
> 'native:extractbyattribute', alg_params, is_child_algorithm=True
>
> )['OUTPUT']
>
> proc_child_lyr = QgsVectorLayer('proc_child', '', 'ogr')
>
> print(f'2. Anzahl Features proc_child_lyr:
> {proc_child_lyr.featureCount()}')
>
>
>
> proc_lyr = processing.run(
>
> 'native:extractbyattribute', alg_params
>
> )['OUTPUT']
>
> print(f'3. Anzahl Features proc_lyr: {proc_lyr.featureCount()}')
>
>
>
> führt zu folgender Ausgabe:
>
>
>
> 1. Anzahl Features log: 0
>
> 2. Anzahl Features proc_child_lyr: -2
>
> 3. Anzahl Features proc_lyr: 4
>
>
>
> Die Tabelle "t_sys_log_leitbild" nimmt über Trigger gesteuert, Änderungen
> eines Layers innerhalb eines GeoPackages entgegen. Horst hat 4 Änderungen
> an
> dem Layer durchgeführt. Die Ausgabe von 3. ist somit korrekt.
>
> Da QGIS von den Änderungen innerhalb der Datenbank nichts mitbekommen hat,
> wird für 1. eine Objektanzahl von 0 ausgegeben. Ist somit nachvollziehbar.
>
> Warum sich allerdings die Ergebnisse von 2. und 3. unterscheiden und wieso
> die Anzahl von Tabelleneinträgen negativ sein kann, bleibt mir
> schleierhaft.
> Kann hier jemand Licht ins Dunkel meiner Gehirnwindungen bringen?
>
> Zudem würde mich ebenfalls interessieren, ob es eine Methode gibt, die das
> Abrufen des aktuellen Zustands einer Datenbanktabelle ermöglicht oder ob
> eine Verbindung zur Datenbank mit SQL-Abfrage den einzig sicheren Weg
> darstellt.
>
>
>
> Mein Dank im Voraus
>
> und schöne Grüße
>
> Bernd
>
>
>
>
>
> --
> ....................................................................
> FOSSGIS-Konferenz 2027 mit OpenStreetMap-Event in Heidelberg!
> 09.-13. März 2027 https://www.fossgis-konferenz.de/
>
> FOSSGIS Vereinstermine:
> https://fossgis.de/aktivit%C3%A4ten/termine/
>
> FOSSGIS e.V, der Verein zur Förderung von Freier Software aus dem
> GIS-Bereich und Freier Geodaten!
> https://www.fossgis.de/ https://mastodon.online/@FOSSGISeV
> ____________________________________________________________________
> FOSSGIS-Talk-Liste mailing list
> FOSSGIS-Talk-Liste at fossgis.de
> https://lists.fossgis.de/mailman/listinfo/fossgis-talk-liste
>
Mehr Informationen über die Mailingliste FOSSGIS-Talk-Liste