String mit Datenbankparametern in Dictionary überführen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
osmi
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 08:43

Hallo,

in QGIS können die Verbindungsparameter für PostGIS/PostgreSQL Layer mittels

Code: Alles auswählen

print iface.activeLayer().dataProvider().dataSourceUri()
abgefragt werden. Anbei ein Beispiel für eine mögliche Ausgabe:

Code: Alles auswählen

dbname='test_db' host=localhost port=5432 user='postgres' password='postgres' sslmode=require key='gid' table="public"."gebaeude" (geom) sql=
Ich möchte aus diesen Verbindungsparametern nun ein Dictionary erstellen. Dabei gibt es folgende Schwierigkeiten:
  • * Die Bezeichnungen für das Schema und die Tabelle oder View sind unter "table" zusammengefasst. Hier ist eine Trennung, bevorzugt in "schema" und "relation", erforderlich.
    * Die Bezeichnung der Spalte mit der Geometrie (z.B. "geom") hat keinen möglichen Schlüssel, sondern befindet sich in einer Klammer.
    * Unter "sql" sind Objektfilter gespeichert, die in QGIS gesetzt werden können. Hier kann alles (z.B. sql="bauhoehe" >= 10) oder nichts stehen.
Ich habe bereits alle Hochkomma entfernt:

Code: Alles auswählen

dbparams = iface.activeLayer().dataProvider().dataSourceUri()
dbparams = dbparams.replace('"', '')
dbparams = dbparams.replace("'", '')
Außerdem habe ich zu Testzwecken die letzten zwölf Zeichen des oben angeführten Strings entfernt und versucht das Ergebnis in ein Dictionairy zu packen:

Code: Alles auswählen

dbparams = dbparams[:-12]
dbparams = dict((item.split('=') for item in dbparams.split(' ')))
Das Ergebnis verwundert mich aber etwas:

Code: Alles auswählen

(u'port', u'5432')
(u'host', u'localhost')
(u'user', u'postgres')
(u'key', u'gid')
(u'sslmode', u'require')
(u'table', u'public.gebaeude')
(u'password', u'postgres')
(u'dbname', u'test_db')
Woher kommen die 'u's und wie kommt die Reihung der Liste zustande? Wie könnte eine saubere Lösung aussehen?

Vielen Dank!
Benutzeravatar
Cronut
User
Beiträge: 34
Registriert: Sonntag 5. Februar 2017, 09:50
Wohnort: HRO, GER

Die Us stehen für Unicode und bezeichnet den Charset der Zeichenkette. Die kannst du einfach konvertieren, wenn dir das nicht passt.

Wegen der Sortierung kann ich nicht im Detail weiterhelfen. Listen habe aber keine vordefinierte Sortierung, sondern sind eigentlich in der Reihenfolge aufgebaut, wie sie erstellt (bzw. Listeknoten hinzugefügt) werden.
“Clean code always looks like it was written by someone who cares.” (Michael Feathers)
Check out: https://awesome-python.com/
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@osmi: hör auf, irgendwelche Stringrepresentationen weiterzuverarbeiten, dazu sind sie nicht gedacht.
›QgsDataSourceUri‹ hat entsprechende Methoden um die Daten abzufragen (was Du aber gar nicht brauchst, weil ein QgsVectorLayer direkt mit der URI arbeiten kann). Außerdem kann diese DataSourceUri auch gleich die SQL-Query mitverwursten.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du bist sicher, dass du die ganzen Angaben nicht auch anderweitig abrufen kannst? Strings per Hand parsen sollte man nur dann, wenn es keine Alternative dazu gibt. Denn so eine Rückgabe kann sich auch schnell mal ändern. Dann stürzt dein Programm mit einer "komischen" Fehlermeldung ab. Öffentliche APIs dagegen ändern sich nicht so schnell. Und wenn es doch mal passiert, dass eine Methode entfernt oder anders benannt wurde, dann kann ein Anwender mit der auftretenden Fehlermeldung oftmals mehr anfangen.
osmi
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 08:43

snafu hat geschrieben:Du bist sicher, dass du die ganzen Angaben nicht auch anderweitig abrufen kannst? Strings per Hand parsen sollte man nur dann, wenn es keine Alternative dazu gibt. Denn so eine Rückgabe kann sich auch schnell mal ändern. Dann stürzt dein Programm mit einer "komischen" Fehlermeldung ab. Öffentliche APIs dagegen ändern sich nicht so schnell. Und wenn es doch mal passiert, dass eine Methode entfernt oder anders benannt wurde, dann kann ein Anwender mit der auftretenden Fehlermeldung oftmals mehr anfangen.
Ja, es scheint tatsächlich einen einfacheren bzw. geeigneteren Weg zu geben, z.B.:

Code: Alles auswählen

dbparams = iface.activeLayer().dataProvider().dataSourceUri()
schema = QgsDataSourceURI(dbparams).schema()
print schema
public
Ich recherchiere mal ein wenig ...jedenfalls danke für den Hinweis und die Hintergrundinformationen!
Antworten