Als erstes sei einmal gesagt, der Code macht exakt das was er soll und bisher habe ich keine Probleme damit. Ich weiß, dass das Rekursionslimit bei Python 1000 ist und es ist zum aktuellen Zeitpunkt nicht absehbar, dass dies je erreicht wird. Aber Rekursionen sind ja selten eine gute Idee, weswegen ich euch fragen wollte, wie kann man es besser machen?
Was soll der Code machen?
Die äußerste Funktion "add_new_machine(data)" wird aufgerufen um das unten gezeigte JSON anzunehmen und die einzelnen Teile in die Datenbank zu schreiben. Das gezeigte JSON-File ist natürlich nur ein Beispiel. Wie viele sub_parts jedes einzelne part haben kann weiß ich derzeit nicht, aber theoretisch bietet dieses Format kein Limit.
Als erstes wird ein Objekt der Klasse DbInterface erzeugt. Dies ist meine eigene Klasse, welche ich bereits sehr häufig verwendet habe und bisher super funktioniert hat. DbInterface verwendet das Modul pyodbc für die Datenbankverbindung.
Anschließend wird in dieser Funktion "überprüft" ob es sich um das richtige JSON-File handelt, indem es nach dem 'machine'-Key sucht. Ich weiß, dass das keine Sicherheit ist, aber derzeit reicht, um zu vermeiden, dass andere JSON-Files aus dem Ordner ausversehen dort eingefügt werden.
Von der Session der DbInterface-Klasse wird das cursor-Objekt erzeugt und in die Funktion übergeben, welche die Rekursion beinhaltet.
Das Scirpt fährt eine Rekursive Loop ab, solange eine "sub_part" weitere "sub_parts" enthält.
Meine 1. Frage, was ist eure Meinung dazu? Geht es besser, wenn ja, wie?
Meine 2. Frage:
Ich hab mittels der Erweiterung "; SELECT scope_identity() as id" im SQL-Statement den erzeugen Primary-Key auf die nächste "row" im cursor gesetzt. (Sagt man da so? / Ist das so richtig?)
Anschließend schalte ich mit:
Code: Alles auswählen
cursor.nextset()
for primary_key in cursor:
print(primary_key)
Ist es egal welchen Namen ich für primary_key in der Loop nehme, alles funktioniert.
Meine Annahme ist ja, dadurch, dass ich im SQL-Statement "; SELECT scope_identity() as id" hinzugefügt habe, gibt es als nächste reihe nur dieses eine Element zum auslesen. Leider verstehe ich nicht, wie ich den Wert aus dem cursor direkt auslese ohne die Loop, weil den Wert des Primary-Keys kann ich beim debuggen nirgendwo im cursor-Objekt erkennen. Wäre hilfreich, wenn mir dort jemand was zu sagen könnte.
Mit freundlichen Güßen an alle, Gera
Code: Alles auswählen
machine_struct.json
{
"meta_data":{
"user":"...",
"date":"...",
"time":"..."
},
"machine":{
"name":"Main",
"machine_id": 2,
"parent_id": 0,
"documents":[
{
"title":"Doc 1",
"reference":"Ref Link"
},
{
"title":"Doc 2",
"reference":"Ref Link"
}
],
"sub_parts":[
{
"name":"PART-XY",
"parent_id": null,
"documents":[
{
"title":"Doc 1",
"reference":"Ref Link"
},
{
"title":"Doc 2",
"reference":"Ref Link"
}
],
"sub_parts":[
{
"name":"PATZ-XX",
"parent_id": null,
"documents":{
"doc1":{
"title":"Doc 1",
"reference":"Ref Link"
},
"doc2":{
"title":"Doc 2",
"reference":"Ref Link"
}
}
}
]
},
{
"name":"Part-XZY",
"parent_id": null,
"documents":[
{
"title":"Doc 1",
"reference":"Ref Link"
},
{
"title":"Doc 2",
"reference":"Ref Link"
}
]
}
]
}
}
Code: Alles auswählen
def add_new_machine(json_struct):
db_config_file_path = PACKAGE_ROOT_DIR + r"\configs\dbconfig.xml"
database_connector = DbInterface(db_config_file_path)
# Check if the Main-Key ('machine') is in the json-file. If not, its the wrong structure
if 'machine' in json_struct:
with database_connector.session as conn:
cursor = conn.cursor()
create_line_and_write_to_db(cursor, json_struct['machine'], parent_id=0)
conn.commit()
else:
print("Wrong JSON-Structure. Cannot find the 'machine'-Key. End of function.")
def create_line_and_write_to_db(cursor, machine_part_element, parent_id):
# Sample Line (DB Columns)
# [Machine_ID], [MS_Name], [belongs_to_MS_ID], [MS_BMK], [MS_Barcode], [MS_image], [Serial_No], [built_date]
db_data = {
"Machine_ID": None,
"MS_Name": None,
"belongs_to_MS_ID": None,
"MS_BMK": None,
"MS_Barcode": None,
"MS_image": None,
"Serial_No": None,
"built_date": None
}
db_data.update({"MS_Name":machine_part_element['name']})
db_data.update({"belongs_to_MS_ID":parent_id})
# TODO: Hier werden noch bedingte Elemente hinzugefügt, derzeit noch nicht Verfügbar
primary_key_inserted_element = write_line_to_db(cursor, db_data)
if 'sub_parts' in machine_part_element:
for part in machine_part_element['sub_parts']:
create_line_and_write_to_db(cursor, part, primary_key_inserted_element)
def write_line_to_db(cursor, data_dict):
table = 'Machine_Sections_Test'
# COPY PASTE + ADAPTION #
# https://stackoverflow.com/questions/9336270/using-a-python-dict-for-a-sql-insert-statement
placeholders = ', '.join(['?'] * len(data_dict))
columns = ', '.join(data_dict.keys())
sql = "INSERT INTO [dbo].[{table}] ( {cols} ) VALUES ( {vals} ); SELECT scope_identity() as id".format(table=table, cols=columns, vals=placeholders)
cursor.execute(sql, list(data_dict.values()))
# ----------------------- #
cursor.nextset()
for primary_key in cursor:
print(primary_key)
return int(primary_key[0])
if __name__ == "__main__":
json_path = r"somewhere\machine_struct.json"
with open(json_path, 'r') as jfile:
data = json.loads(jfile.read())
add_new_machine(data)