Datenbanktabellen mithilfe eines scriptes anlegen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Ich habe jetzt sehr lange nach einer Lösung im Internet gesucht. Ich bekomme folgende Fehlermeldung:

ValueError: time data 'Date' does not match format 'Time'

Ja, das ist richtig. weil das Format in der CSV Datei 01.03.2016, 19:30:00, (Monat, Tag, Jahr) ist. Die richtige Syntax von Time aber datetime.strptime('2012-11-14 14:32:30', '%Y-%m-%d %H:%M:%S') ist. Ich möchte das Datum und Zeitformat auf keinen Fall verändern.

Bitte schaut Euch einmal den Code an. Ist das soweit richtig? Ist der \ für den Umbruch richtig, dmit die Zeilen nicht zu lang werden?

Code: Alles auswählen

#!/usr/bin/python
# -*- coding:utf-8 -*-

import csv
import datetime
import glob
import MySQLdb
import os

# Traverse the directory and process each .csv file
for csvfile in glob.glob('data/*.csv'):

# Remove the path and extension and use what's as a table name
    table_name = os.path.splitext(os.path.basename(csvfile))[0]
    print (table_name)

# Read data from the csv File(s)
    with open(csvfile, "rb") as sourcefile:
        print(' ')
        reader = csv.DictReader(sourcefile, delimiter = ',')
        for row in reader:
            print("{Date}, {Time}, {Open}, {High}, {Low}, {Close}".format(**row))

    Datetime = datetime.datetime.strptime("Date","Time")

try:
    db = MySQLdb.connect(host="localhost", user="usr", passwd="passwd", db="db")

    cursor = db.cursor()

    sql = """INSERT INTO CURRENCY(AUDCAD, AUDJPY, AUDNZD, AUDUSD, CADJPY, EURAUD, EURCAD, EURCHF, \
                                  EURGBP, EURJPY, EURNZD, EURUSD, GBPAUD, GBPJPY, GBPUSD, NZDJPY, \
                                  USDCAD, USDCHF, USDJPY, Datetime, Open, High, Low, Close)
             Values("%s", "%s", "%s", "%s", "%s","%s", "%s", "%s", "%s", "%s","%s", "%s", "%s", \
                    "%s", "%s","%s", "%s", "%s", "%s", "%s","%s", "%s", "%s", "%s")"""

    cursor.execute(sql)
    db.commit()
    db.rollback()


except MySQLdb.Error, e:
    print "Error %d: %s" % (e.args[0],e.args[1])

finally:
    if db:
        db.close()
Zuletzt geändert von Anonymous am Samstag 3. Dezember 2016, 20:23, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@aaron: Natürlich ist die Fehlermeldung richtig, aber ich denke Du hast sie nicht wirklich verstanden. Du versuchst dort den Wert 'Date', also die Zeichenkette die aus 'D', 'a', 't', und 'e' besteht, als Datum zu parsen. Das ist schon mal falsch weil das Wort 'Date' kein Datum ist. Und die Zeichenkette 'Time' ist auch kein Muster um eine Zeichenkette mit einem tatsächlichen Datum zu parsen.

Beim Beispielaufruf von `strptime()` hat die Zeichenkette mit der Datums- und Zeitangabe ein anderes Format als Deins. Also musst Du für Dein Format auch entsprechend das Muster anpassen das als zweites Argument übergeben wird. Was die Platzhalter bedeuten und welche es noch so gibt, steht in der Python-Dokumentation.

Der Quelltext ist nicht wirklich richtig. Zum Beispiel macht Zeile 24 nicht nur von den Argumenten her keinen Sinn, sondern auch die Stelle im Programmablauf an der das steht ist nicht sinnvoll. Das gilt im Grunde auch für den ganzen Rest des Programms ab dort. Allerdings sollte man das jetzt auch nicht einfach an die richtige Stelle ”verschieben”, denn dann bist Du auf dem besten Weg einen immer überfrachteteren, unübersichtlichen Code-Klumpen zu schreiben, wo man nichts mal eben isoliert testen kann. Leg das am besten mal beiseite und arbeite ein Grundlagentutorial durch um den grundsätzlichen Programmablauf und wie man den mit Schleifen und anderen Konstrukten steuern kann, kennen zu lernen.

Und dabei wirst Du dann auch Funktionen kennen lernen, und wie man die schreibt. Denn das was Du da machst ist gross genug dass man das sinnvoll auf Funktionen aufteilen kann, damit es übersichtlicher und test- und damit auch wartbarer wird. Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Eine übliche grobe Aufteilung ist Eingabe/Verarbeitung/Ausgabe. Du könntest also eine Funktion schreiben, die *eine* Datei einliest und die Werte entsprechend in Werte umwandeld mit denen man im Programm arbeiten möchte. Also Datums- und Zeitangaben in passende Datentypen aus dem `datetime`-Modul und Zahlen je nach Wertebereich als `int` oder `float`.

Dann kann man eine Funktion schreiben die solche eingelesenen Werte in die Datenbank schreibt.

Und dann eine die in einer Schleife die beiden Funktionen für alle Dateien anwendet.

Ein wichtiger Teil beim Programmieren ist das aufteilen vom Gesamtproblem in Teilprobleme und die wieder in weitere Teilprobleme, solange bis man welche hat, die einfach mit ein paar Zeilen Code lösbar sind. Die Teillösung testet man, und wenn sie tut was sie soll, kann man anfangen die kleineren Teillösungen in ”höheren” Teillösungen zu verwenden, und die dann auch wieder testen, bis man alles zu einer funktionierenden Gesamtlösung zusammen gesetzt hat. Du versuchst da zu viel auf einmal. Solange das einlesen einer Datei noch nicht funktioniert, braucht man sich um Code der die noch gar nicht im Programm verfügbaren Daten in die Datenbank einfügt noch nicht wirklich kümmern, denn man kann zu dem Zeitpunkt ja sowieso noch nicht testen ob der funktioniert oder nicht.

Die INSERT-Anweisung mit den ganzen Währungspaaren als *Spaltennamen* sieht komisch bis falsch aus. Die '\' am Ende sind unnötig da die """ als Begrenzer für das Zeichenkettenliteral ja schon dafür sorgen das es ein mehrzeiliges Zeichenkettenliteral ist. Die " um die Platzhalter gehören da nicht hin. Und wenn man Platzhalter in der SQLAnweisung hat, dann muss man dafür beim `execute()`-Aufruf auch die passenden Werte übergeben.

Ein `rollback()` direkt nach einem `commit()` macht keinen Sinn.

Das öffnen der Datenbankverbindung müsste vor dem ``try`` für das ``finally`` stehen. Aber in dem ``try`` für das ``except``. Also eigentlich braucht man ein ``try``/``except`` und ein ``try``/``finally`` für das was da passieren soll. Oder man verwendet ``with`` in Verbindung mit `contextlib.closing()` statt des ``try``/``finally``.

Das ``if db:`` ist sinnfrei, denn wenn der Verbindungsaufbau zu einer Ausnahme führt, dann ist `db` nicht definiert und das Programm läuft dort in einen `NameError` oder der Verbindungsaufbau hat geklappt, dann ist aber ``if db:`` auch Grundsätzlich ”wahr” weil solche Verbindungsobjekte keinen Wert annehmen der als Bedinung ”falsch” ergibt.
Antworten