Ändern von Bezeichnungen in einer Liste
@andyritter: es geht nicht darum, was Du jetzt mit diesen Datenstrukturen machst, sondern darum, was Du irgendwann einmal damit machst, und dann ist es immer sinnvoll, beim Programmieren so wenig Kollateralschäden anzurichten wie geht. Zudem Du weiter oben geschrieben hast, dass Du die anderen Keys noch umbenennen willst, so dass von Deinem ursprünglichen Wörterbuch nichts übrig bleibt.
- DeaD_EyE
- User
- Beiträge: 1017
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Manchmal sind die Daten einfach zu sehr verschachtelt und man verliert schnell den Überblick. Zumindest geht es mir so.
Ich versuche das dann immer in der Repl auseinander zu nehmen. Wichtig ist, dass man genau weiß was für ein Datentypen vorliegen und welche bei der Iteration ausgegeben werden, damit man die passenden Methoden verwendet und überhaupt weiß was man dort macht. Also du hast ein dict, in dem der Schlüssel der Name der Liste ist und der Wert eine Liste mit Dicts.
Mit dict.items() liefert eine Tupel mit key, value (generator in Python3). Falls es Python2.7 ist, sollte man dict.iteritems() verwenden um Speicher zu sparen. Iteriert man über value nochmals, bekommt man die Elemente aus der Liste, die dicts sind. Dann noch im Hinterkopf behalten, dass dicts mutable Datentypen sind. D.h. Methoden, die du darauf anwendest, verändern das Objekt innerhalb der Liste. Die Liste ist natürlich auch mutable.
Am besten baust du dir eine Klasse um die Daten herum.
Ich versuche das dann immer in der Repl auseinander zu nehmen. Wichtig ist, dass man genau weiß was für ein Datentypen vorliegen und welche bei der Iteration ausgegeben werden, damit man die passenden Methoden verwendet und überhaupt weiß was man dort macht. Also du hast ein dict, in dem der Schlüssel der Name der Liste ist und der Wert eine Liste mit Dicts.
Mit dict.items() liefert eine Tupel mit key, value (generator in Python3). Falls es Python2.7 ist, sollte man dict.iteritems() verwenden um Speicher zu sparen. Iteriert man über value nochmals, bekommt man die Elemente aus der Liste, die dicts sind. Dann noch im Hinterkopf behalten, dass dicts mutable Datentypen sind. D.h. Methoden, die du darauf anwendest, verändern das Objekt innerhalb der Liste. Die Liste ist natürlich auch mutable.
Code: Alles auswählen
l = {'List1': [{'description': 'What ever',
'enabled': False,
'id': '1234',
'name': 'abc'},
{'description': 'What ever2',
'enabled': True,
'id': '3456',
'name': 'def'},
{'description': 'What ever 3',
'enabled': True,
'id': '6789',
'name': 'ghi'}],
'Liste 2': []}
def change_state(data, id, enabled=False):
for key, value in data.items():
for item in value:
if item.get('id') == str(id):
item.update({'enabled': enabled})
change_state(l, 1234, True)
print([element for key, value in l.items() for element in value if element.get('id') == '1234'])
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Falls damit gemeint ist, dass bloß triviale Getter und Setter für die einzelnen Schlüssel gebastelt werden sollen, um an den zugehörigen Wert zu kommen, dann würde ich den Einsatz von Klassen hier *nicht* empfehlen, weil ich den Mehrwert in diesem Fall für fragwürdig halte. Die Umsetzung deines Vorschlags findet man zwar oft z.B. in der Java-Welt, aber in Python ist es üblich, dass ein nacktes Dictionary Teil der API ist und dass deshalb keine Wrapper-Klasse um die Daten gebaut wird.DeaD_EyE hat geschrieben:Am besten baust du dir eine Klasse um die Daten herum.
Falls etwas anderes gemeint ist, dann wären Details, wie diese Klasse aussehen soll bzw was sie tun soll, hilfreich.
Bei meiner Begründung stand die geringere Komplexität des Codes im Vordergrund, die man durch das Weglassen von `del`-Statements erreicht. Wie gesagt: Der zusätzliche Speicherverbrauch wirkt sich oft nicht spürbar aus, sodass der Vorteil, den man durch `del` zu haben glaubt, in der Praxis eigentlich nicht zum Tragen kommt. Zumal genau genommen gar nicht garantiert ist, wann ein durch `del` zum Löschen freigegebenes Objekt auch wirklich aus dem Speicher gelöscht wird. Das kann prinzipiell viel später passieren, als du denkst.andyritter hat geschrieben:Der Hinweis mit der Kopie ist schon bei mir angekommen, doch ich benötige die Quelldaten ja nicht weiter, daher kann ich das meiner Meinung nach auch wirklich löschen.
Aber gut: Letztlich ist es eine Frage des persönlichen Stils, ob man neue Dictionaries anlegt (und dadurch Codezeilen einspart) oder ob man lieber bereits bestehende Dictionaries verändert. Richtig schlecht wird der Einsatz von `del` erst bei Listen, weil dann unter Umständen (je nach Implementierung) intern eine Neuordnung der Daten erfolgen muss, wenn man mit `del` irgendwelche Elemente herausgepflückt hat. Und das ist dann gar nicht mehr so vorteilhaft in Hinblick auf die Performance des Programms.
-
- User
- Beiträge: 29
- Registriert: Montag 7. März 2016, 16:27
Vielen Dank für eure Erläuterungen,
ich habe mich dazu entschieden, die Datensätze direkt in die Datenbank zu schreiben ohne zuvor etwas zulöschen oder anzupassen.
for item in t['tenants']:
osp_tenants_tenant_id = item['id']
osp_tenants_name = item['name']
osp_tenants_description = item['description']
print(osp_tenants_tenant_id)
print(osp_tenants_name)
print(osp_tenants_description)
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""",(osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description)
was mir hierbei noch nicht gelungen ist, ist die Prüfung der Tabelle mit IF EXISTS. das ist dann jedoch eine neuer Thread, oder?
ich habe mich dazu entschieden, die Datensätze direkt in die Datenbank zu schreiben ohne zuvor etwas zulöschen oder anzupassen.
for item in t['tenants']:
osp_tenants_tenant_id = item['id']
osp_tenants_name = item['name']
osp_tenants_description = item['description']
print(osp_tenants_tenant_id)
print(osp_tenants_name)
print(osp_tenants_description)
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""",(osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description)
was mir hierbei noch nicht gelungen ist, ist die Prüfung der Tabelle mit IF EXISTS. das ist dann jedoch eine neuer Thread, oder?
Normalerweise ja, aber wir sehen das hier nicht ganz so eng. Solange das hier kein Sammelthread für deine Fragen der nächsten 12 Monate wird, denke ich, dass es in Ordnung geht, wenn du die Frage hier im Thread stellst.
-
- User
- Beiträge: 29
- Registriert: Montag 7. März 2016, 16:27
@snafu: ok, dann frage ich mal nach
Hier der Teil für den Insert erweitert um die Eingrenzung
erhalte ich immer Invalid Syntax und die Markierung steht auf dem letzten " vor
,(osp_tenants_tenant_id))
conn.commit()
Mein Ziel ist es, die Werte die in der Datenbank sind nicht nochmal einzufügen
ich hab schon so viel verschiedenes in Internet gelesen, aber einen besseren Ansatz habe ich noch nicht gefunden
Hier der Teil für den Insert erweitert um die Eingrenzung
Code: Alles auswählen
for item in t['tenants']:
osp_tenants_tenant_id = item['id']
osp_tenants_name = item['name']
osp_tenants_description = item['description']
print(osp_tenants_tenant_id)
print(osp_tenants_name)
print(osp_tenants_description)
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""",(osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description)\
"""(if not exists (select tenant_id from osp_tenants where tenant_id = %s)""",(osp_tenants_tenant_id))
conn.commit()
,(osp_tenants_tenant_id))
conn.commit()
Mein Ziel ist es, die Werte die in der Datenbank sind nicht nochmal einzufügen
ich hab schon so viel verschiedenes in Internet gelesen, aber einen besseren Ansatz habe ich noch nicht gefunden
Zuletzt geändert von Anonymous am Montag 21. März 2016, 17:32, insgesamt 1-mal geändert.
Grund: Quelltext in Code-Tags gesetzt.
Grund: Quelltext in Code-Tags gesetzt.
@andyritter: Das ist halt kein gültiges Python. Und AFAIK wird das auch in SQL so nicht möglich sein mit einem bedingten Einfügen.
Entweder fragt man vorher die ID ab, oder man deklariert die als UNIQUE (falls das nicht sowieso schon der Primärschlüssel ist) und behandelt die auftretende Ausnahme entsprechend.
Entweder fragt man vorher die ID ab, oder man deklariert die als UNIQUE (falls das nicht sowieso schon der Primärschlüssel ist) und behandelt die auftretende Ausnahme entsprechend.
- miracle173
- User
- Beiträge: 127
- Registriert: Samstag 6. Februar 2016, 00:28
@snafu: Wenn normalerweise ja, warum jetzt nicht? Es ist eigentlich nicht sinnvoll, eine andere Frage hier zu posten. Es passt nicht zum Thread-Titel, ist als Frage nicht zu finden und wenn jemand nocht etwas zur ursprünglichen Frage posten will, ergibt das dann ein völliges Durcheinander von Antworten. Einen Vorteil kann ich eigentlich keinen erkennen.
mfg miracle173
https://github.com/python-forum-de/Jump-N-Run-pydesw
https://github.com/python-forum-de/Jump-N-Run-pydesw
@miracle173
Prinzipiell hast du Recht. Ich stimme deiner Begründung völlig zu.
Es ist aber jetzt auch kein Beinbruch für mich. Und ich weiß, dass auch in anderen Threads schon Folgefragen gestellt wurden, die zwar auf dem ursprünglichen Thema aufgebaut haben, aber streng genommen hätte man sie isoliert in einem eigenen Thread stellen müssen.
Wenn es dir ein wichtiges Anliegen ist, die beiden Themen zu trennen, dann wende dich am besten direkt an die Moderatoren (z.B an BlackJack), damit der Thread nachträglich gesplittet wird.
Wie gesagt: Mir ist es ehrlich gesagt egal, wenn man ausnahmsweise den selben Thread für eine Folgefrage nutzt. Es sollte nur nicht zur Regelmäßigkeit werden.
Prinzipiell hast du Recht. Ich stimme deiner Begründung völlig zu.
Es ist aber jetzt auch kein Beinbruch für mich. Und ich weiß, dass auch in anderen Threads schon Folgefragen gestellt wurden, die zwar auf dem ursprünglichen Thema aufgebaut haben, aber streng genommen hätte man sie isoliert in einem eigenen Thread stellen müssen.
Wenn es dir ein wichtiges Anliegen ist, die beiden Themen zu trennen, dann wende dich am besten direkt an die Moderatoren (z.B an BlackJack), damit der Thread nachträglich gesplittet wird.
Wie gesagt: Mir ist es ehrlich gesagt egal, wenn man ausnahmsweise den selben Thread für eine Folgefrage nutzt. Es sollte nur nicht zur Regelmäßigkeit werden.
-
- User
- Beiträge: 29
- Registriert: Montag 7. März 2016, 16:27
@BlackJack: Ich habe die Spalte als UNIQUE deklariert. Danke für den Hinweis.
Ich habe den Insert wie folgt gelöst:
Weitere Fragen werde ich in einem Neuen Thread stellen
Danke an alle für Eure Unterstützung.
Ich habe den Insert wie folgt gelöst:
Code: Alles auswählen
# Einfügen der Werte aus der Tenant Abfrage
for item in t['tenants']:
osp_tenants_tenant_id = item['id']
osp_tenants_name = item['name']
osp_tenants_description = item['description']
#print(osp_tenants_tenant_id ,osp_tenants_name, osp_tenants_description)
try:
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""", (osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description))
print("Neuer Eintrag:", osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description)
except:
print(osp_tenants_tenant_id,"schon vorhanden")
print("-------------------------------------------------------")
Danke an alle für Eure Unterstützung.
Zuletzt geändert von Anonymous am Dienstag 22. März 2016, 11:55, insgesamt 1-mal geändert.
Grund: Quelltext in Code-Tags gesetzt.
Grund: Quelltext in Code-Tags gesetzt.
@andyritter: Nackte ``except:``\s sind keine gute Idee. Du behandelst hier *jede* Ausnahme so als wäre die ID schon vorhanden, auch wenn die Ausnahme einen ganz anderen Grund hat. Zum Beispiel ein Programmierfehler, oder ein Netzwerkproblem, oder das die Datenbank nicht (mehr) erreichbar ist, oder…
-
- User
- Beiträge: 29
- Registriert: Montag 7. März 2016, 16:27
@BlackJack: Wie kann ich denn einen IOError ausklammern, dass das Script weiter ausgeführt wird? Wenn ich den IOError mit aufführe,BlackJack hat geschrieben:@andyritter: Nackte ``except:``\s sind keine gute Idee. Du behandelst hier *jede* Ausnahme so als wäre die ID schon vorhanden, auch wenn die Ausnahme einen ganz anderen Grund hat. Zum Beispiel ein Programmierfehler, oder ein Netzwerkproblem, oder das die Datenbank nicht (mehr) erreichbar ist, oder…
Code: Alles auswählen
for item in t['tenants']:
osp_tenants_tenant_id = item['id']
osp_tenants_name = item['name']
osp_tenants_description = item['description']
#print(osp_tenants_tenant_id ,osp_tenants_name, osp_tenants_description)
try:
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""", (osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description))
print("Neuer Eintrag:", osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description)
except IOError as e:
print(osp_tenants_tenant_id,"schon vorhanden")
print("-------------------------------------------------------")
else:
print("alles ok")
erscheint diese Fehlermeldung:
Traceback (most recent call last):
File "/home/akquinet/Dokumente/Database_insert_tenants.py", line 76, in <module>
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""", (osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description))
IntegrityError: duplicate key value violates unique constraint "osp_tenants_tenant_id_key"
DETAIL: Key (tenant_id)=(abcd) already exists.
Bei allen Möglichkeiten,die ich bei Google gefunden habe wird diese Fehlerbehandlung nicht dargestellt oder ich verstehe es nicht.
Zuletzt geändert von Anonymous am Donnerstag 24. März 2016, 09:59, insgesamt 1-mal geändert.
Grund: Quelltext in Code-Tags gesetzt.
Grund: Quelltext in Code-Tags gesetzt.
@andyritter: Du behandelst einen `IOError` (warum?), und bekommst bei einer bereits vorhandenen `tenant_id` einen `IntegrityError`. Finde den Fehler.
-
- User
- Beiträge: 29
- Registriert: Montag 7. März 2016, 16:27
@BlackJAck: Wenn ich den IntegrityError abfangen will mit:
Erhalte ich diese Fehlermeldung:
Traceback (most recent call last):
File "/home/akquinet/Dokumente/Database_insert_tenants.py", line 78, in <module>
except IntegrityError as e:
NameError: name 'IntegrityError' is not defined
Wobei mich dann wiederum stutzig macht, dass die Fehlerbezeichnung nicht definiert sein soll.
Code: Alles auswählen
for item in t['tenants']:
osp_tenants_tenant_id = item['id']
osp_tenants_name = item['name']
osp_tenants_description = item['description']
#print(osp_tenants_tenant_id ,osp_tenants_name, osp_tenants_description)
try:
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""", (osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description))
print("Neuer Eintrag:", osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description)
except IntegrityError as e:
print(osp_tenants_tenant_id,"schon vorhanden")
print("-------------------------------------------------------")
else:
print("alles ok")
Traceback (most recent call last):
File "/home/akquinet/Dokumente/Database_insert_tenants.py", line 78, in <module>
except IntegrityError as e:
NameError: name 'IntegrityError' is not defined
Wobei mich dann wiederum stutzig macht, dass die Fehlerbezeichnung nicht definiert sein soll.
Zuletzt geändert von Anonymous am Donnerstag 24. März 2016, 10:23, insgesamt 1-mal geändert.
Grund: Quelltext in Code-Tags gesetzt.
Grund: Quelltext in Code-Tags gesetzt.
- miracle173
- User
- Beiträge: 127
- Registriert: Samstag 6. Februar 2016, 00:28
Code: Alles auswählen
Traceback (most recent call last):
File "/home/akquinet/Dokumente/Database_insert_tenants.py", line 76, in <module>
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""", (osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description))
IntegrityError: duplicate key value violates unique constraint "osp_tenants_tenant_id_key"
DETAIL: Key (tenant_id)=(abcd) already exists.
in etwa
Beim Ausführen von
cur.execute("""INSERT INTO osp_tenants (name, tenant_id, description) VALUES (%s, %s, %s)""", (osp_tenants_name, osp_tenants_tenant_id, osp_tenants_description))
Anmerkung von mir: das ist das Einfügen eines Datensatzes in die Datenbank
in der Zeile 76 der Datei "Database_insert_tenants.py" gabs den
Integritäts-Fehler: doppelter Schlüsselwert verletzt die Eindeutigkeitsbeschränkung "osp_tenants_tenant_id_key"
Detail: Den Schlüssel (tenant_id)=(abcd) gibt es schon.
Was ist dir daran nicht klar?
mfg miracle173
https://github.com/python-forum-de/Jump-N-Run-pydesw
https://github.com/python-forum-de/Jump-N-Run-pydesw
@andyritter: Das ist eine Ausnahme die spezifisch für Datenbanken ist, natürlich fällt das nicht einfach so vom Himmel und ist auf magische Weise verfügbar. Du musst die Ausnahme schon aus dem Modul importieren in dem sie definiert wurde, wie alle anderen Datentypen ausser den eingebauten halt auch.
-
- User
- Beiträge: 29
- Registriert: Montag 7. März 2016, 16:27
@miracle: Mir ist nicht klar, wie ich es fertig bringe, dass das Script weiterläuft, auch wenn für einen Datensatz ein "IntegrityError: duplicate key value violates unique constraint" geworfen wird.
@BlackJack: Leider habe ich keine Ahnung, in welchem Modul dieser Fehler definiert sein soll. Kannst Du mir da einen Tipp geben?
Danke schön
@BlackJack: Leider habe ich keine Ahnung, in welchem Modul dieser Fehler definiert sein soll. Kannst Du mir da einen Tipp geben?
Danke schön
@andyritter: Nee, kann ich nicht. Ich bin gerade zu sehr mit kopfschütteln beschäftigt. In welchem Modul mag wohl der Ausnahmetyp für Datenbankfehler definiert sein… Wie soll man da bloss drauf kommen…
-
- User
- Beiträge: 29
- Registriert: Montag 7. März 2016, 16:27
except psycopg2.IntegrityError: