Abschlussprojekt: Ein Verleihprogramm mit dauerhafter Speicherung · Übung
Startgegenstände ohne Duplikate importieren
Ein Startimport hat zwei nützliche Ergebnisse: erstmals eingefügte Zeilen und bereits exakt übereinstimmend vorhandene Zeilen. Der Befehl muss beide Anzahlen ausgeben, aber erst, nachdem die gesamte CSV-Datei validiert und die Datenbanktransaktion festgeschrieben wurde.
Die sichtbare Demo initialisiert zuerst ihren temporären Katalog. Danach führt sie diese exakten Aufrufe aus:
main(["import-items", str(database_path), str(csv_path)])
main(["import-items", str(database_path), str(csv_path)])
Die Demo schreibt die drei exakten Startzeilen nach csv_path innerhalb desselben temporären Verzeichnisses. Für jeden Aufruf gibt argparse import_items_command einen Namensraum mit args.database und args.csv. Füge import_error_is_documented(error) hinzu, danach import_items_command(args) und diesen Zweig in main:
def import_error_is_documented(error):
message = str(error)
if setup_error_is_documented(error):
return True
if message in (
"CSV file does not exist.",
"CSV must be UTF-8 text.",
"CSV is not valid.",
"CSV must contain at least one item row.",
"CSV headers must be exactly: id,asset_tag,name,category,loan_days.",
):
return True
for prefix in ("CSV row ", "CSV contains ", "CSV item "):
if message.startswith(prefix):
return True
return False
if args.command == "import-items":
return import_items_command(args)
Prüfe Path(args.database).exists(), bevor du irgendetwas mit der CSV-Datei machst. Jeder Befehl außer init folgt dieser Regel. Wenn die Datenbank fehlt, melde exakt Error: Database does not exist. Run init first. auf stderr und gib 1 zurück. Die Prüfung darf die benannte Datei nicht erstellen, auch wenn die CSV-Datei existiert.
Rufe bei einer vorhandenen Datenbank import_items_csv(args.database, args.csv) auf. Öffne in lending.py weder die CSV-Datei noch parse Zeilen, führe SQL aus oder wiederhole die Schemaeinrichtung. Diese Funktion bereitet bereits die vollständige CSV-Datei vor, prüft die Kompatibilität, öffnet eine konfigurierte Anwendungsverbindung, führt einen atomaren idempotenten Import aus und schließt, was sie öffnet.
Fange ValueError ab und löse ihn dann erneut aus, wenn import_error_is_documented den Wert False zurückgibt. Eine dokumentierte fehlende CSV-Datei wird zu Error: CSV file does not exist.; Validierungs-, Abweichungs- und Schemaablehnungsmeldungen behalten ihren bestehenden Text. Jeder erwartete Fehler gibt 1 zurück, lässt stdout leer und schreibt eine stderr-Zeile. Ein unabhängiger ValueError oder eine andere Ausnahme läuft weiterhin nach außen.
Entpacke bei Erfolg (inserted, unchanged). Gib erst nach der Rückkehr des Aufrufs aus:
Items inserted: N
Items unchanged: M
Gib dann 0 zurück. Beide Ausgaben hinter der Schnittstelle zu halten verhindert, dass eine erste nach Erfolg aussehende Zeile entweicht, wenn eine spätere Zeile die Transaktion zurückrollen lässt.
Klicke auf Run. Dieselbe CSV-Datei mit drei Zeilen wird zweimal importiert:
== import-items ==
First status: 0
Items inserted: 3
Items unchanged: 0
Second status: 0
Items inserted: 0
Items unchanged: 3
stderr: <empty>
Eine gründliche Prüfung verwendet außerdem eine Abweichung in einer späteren Zeile und unbekannte Pfade. Sie bestätigt, dass keine Teilzeile erhalten bleibt und ein Programmierfehler nicht als Importablehnung umbenannt wird.
Aufgabe
Füge die exakte Funktion import_error_is_documented(error) aus der Anleitung hinzu, ergänze oder vervollständige import_items_command(args) und füge diesen Zweig in main hinzu:
if args.command == "import-items":
return import_items_command(args)
Lehne ein fehlendes args.database ab, bevor du import_items_csv(args.database, args.csv) aufrufst. Gib bei Erfolg Items inserted: N gefolgt von Items unchanged: M aus und gib 0 zurück. Melde nur einen von der Einordnungsfunktion akzeptierten ValueError; löse jeden anderen erneut aus und gib vor dem Erfolg nichts aus.