Bestimmte Spaltenköpfe einer CSV Datei in eine DB importiere

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
Brooklyn
User
Beiträge: 5
Registriert: Montag 11. Januar 2010, 08:16

Hallo zusammen,

ich habe mir gedacht, das es an der Zeit ist mal eine Programmiersprache zu lernen. Ein Kollege hat mich da auf Python gebracht und bis jetzt muß ich sagen, das ich sie sehr übersichtlich finde - macht richtig Spaß sich damit zu beschäftigen.

Ich habe mir auch ein Projekt einfallen lassen, das quasi eine Datei per FTP von einem Host runterlädt. Schaut, ob eine SQLite DB Vorhanden ist und wenn ja diese dann löscht und dann wieder neu anlegt ( Ich bin Anffänger und weiß es nicht besser ).
Nach dem diese DB angelegt worden ist, sollen dann aus einer CSV Datei nur ausgewählte Spalten importiert werden. Quasi nur 3 aus 13 Spalten.

Angefangen habe ich bis jetzt so:

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-
import sqlite3
import csv
import os
import sys
import ftplib

# FTP Abschnitt ANFANG

ftp = ftplib.FTP()
ftp.connect("Host")
ftp.login("Username", "Passwort")
ftp.set_pasv(True)

def handleDownload(block):
    file.write(block)

filename = 'accountdata.csv'
file = open(filename, 'wb')
ftp.retrbinary('RETR ' + filename, handleDownload
file.close()ftp.quit()

# FTP Abschnitt ENDE
# SQLITE Abschnitt ANFANG

if os.path.isfile(r"C:\testumail.db"):
 os.remove(r"C:\testumail.db")
cur = conn.cursor()
# Erstellen der Haupttables
sql = """
CREATE TABLE usermail (
username VARCHAR(8)  NULL,
email VARCHAR(30)  UNIQUE NOT NULL PRIMARY KEY,
company INTEGER  NULL
)
"""
conn.execute(sql)
conn.commit()
# Erstellen des Indexes
sql = """
CREATE UNIQUE INDEX IDX_USERMAIL_ ON usermail(email  ASC)
"""
conn.execute(sql)
conn.commit()

.....
.....
#Platz fuer den CSV Import
.....
conn.close()
Was mir noch fehlt, ist jetzt eine Funktion, die mir aus bestimmten Spaltenköpfen einer csv Datei ausgewählte Spalten in den Table der SQLlite Datenbank importiert. Nur ich sehe mittlerweile den Wald vor lauter Bäumen nicht. Ich habe zwar das Forum, die Doku gewälz, aber wirklich schlau bin ich nicht weiter geworden:

Code: Alles auswählen

in_file = open(r"C:\baan_accountdata.csv", "r")
reader = csv.reader (in_file, delimiter=";")
for row in reader:
    print (row)

in_file.close()
Ergibt dann bei mir das Ausgabe Ergebnis:
['4711', 'mmustermann', 'Max', 'Mustermann', 'mmustermann@musterdomain.org', 'xxx', 'xxx', 'Yes', 'NO']

Wie müßte ich jetzt ungefähr vorgehen, wenn ich nur eine bestimme Auswahl der Spalten importieren möchte ( Nummer, Username, E-Mail)?
Die CSV Datei hat auch Spaltenköpfe, die auch per ";" von einander getrennt sind.

Spaltenkopf 1 > Nummer
Spaltenkopf 2 > Username
Spaltenkopf 3 > Vorname
Spaltenkopf 4 > Nachname
Spaltenkopf 5 > E-Mail
....

Hölp!!!!! :D

Gruß

Brooklyn
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Brooklyn hat geschrieben:

Code: Alles auswählen

['4711', 'mmustermann', 'Max', 'Mustermann', 'mmustermann@musterdomain.org', 'xxx', 'xxx', 'Yes', 'NO']
Wie müßte ich jetzt ungefähr vorgehen, wenn ich nur eine bestimme Auswahl der Spalten importieren möchte ( Nummer, Username, E-Mail)?
Was du da vorliegen hast ist eine Liste. Du kannst problemlos auf jedes einzelne Element über seinen Index zugreifen wobei die Zählung bei 0 beginnt.

Code: Alles auswählen

In [1]: data = ['4711', 'mmustermann', 'Max', 'Mustermann', 'mmustermann@musterdomain.org', 'xxx', 'xxx', 'Yes', 'NO']

In [2]: print data[0]
------> print(data[0])
4711

In [3]: print data[4]
------> print(data[4])
mmustermann@musterdomain.org
BlackJack

@Brooklyn: An der Stelle vielleicht mal der Hinweis auf das Tutorial in der Python-Dokumentation, welches man auf jeden Fall einmal durchgearbeitet haben sollte.

Ausserdem könnte es Sinn machen, wenn Du Funktionen verwendest, statt einfach alles so linear auf Modulebene herunterzuschreiben. Dann könnte man einzelne Teillösungen unabhängig vom Rest entwickeln und testen.

Eine nette Funktion um mehrere Indexe auf einmal abzufragen ist übrigens `operator.itemgetter()`.

Wenn Du die Datenbank neu erstellst, könnte man den Index in der DB auch *nach* dem Importieren der Daten anlegen. Das geht unter Umständen schneller.
Brooklyn
User
Beiträge: 5
Registriert: Montag 11. Januar 2010, 08:16

Schon mal Danke für die Infos. Werde mich mal weiter mit den Infos beschäftigen
Brooklyn
User
Beiträge: 5
Registriert: Montag 11. Januar 2010, 08:16

Guten Morgen,

habe mich gestern wieder mit dem Teil des Scripts beschäftigt, der drei bestimmte Spalten parsen soll und die dann in die Datenbank importiern soll:

Code: Alles auswählen

rfilename = r"C:\test.csv"
try:
    reader = csv.reader(open(rfilename, "rt"), delimiter =";")
    
except:
    print ("Can´t use file")

for column in reader:
    comp = column[0]
    user = column[1]
    mail = column[4]
    sql = "INSERT INTO usermail (comp, user, mail) VALUES ( "+comp+", '"+user+"', '"+mail+"' )"
    print (comp)

try:
    cursor.execute(sql)
    connection.commit()

except: 
    print ("ERROR: Can´t insert data")
    connection.rollback()
Das print (comp) habe ich deswegen eingefügt, damit ich sehen kann, ob die Variabeln übergeben werde. Soweit klappt auch alles, aber leider wird immer nur ein Datensazu hinzugefügt und zwar immer der Letzte.

Hatte gedacht, das es erst an der Menge 1000> liegt, aber das passiert auch bei nur 10.

Was ich nicht verstehe. Beim Anzeigen des SQL Statements auf dem Bildschrim, läuft das Statement solange durch, wie es rows gibt, nur wieso wird nur ein Datensatz in die DB eingetrage. Liegt es vielleicht daran, dass ich nur ein Commit am Ende schreibe?

Gruß

Brooklyn
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Brooklyn hat geschrieben:

Code: Alles auswählen

for column in reader:
    comp = column[0]
    user = column[1]
    mail = column[4]
    sql = "INSERT INTO usermail (comp, user, mail) VALUES ( "+comp+", '"+user+"', '"+mail+"' )"
    print (comp)

try:
    cursor.execute(sql)
    connection.commit()

except: 
    print ("ERROR: Can´t insert data")
    connection.rollback()
Das print (comp) habe ich deswegen eingefügt, damit ich sehen kann, ob die Variabeln übergeben werde. Soweit klappt auch alles, aber leider wird immer nur ein Datensazu hinzugefügt und zwar immer der Letzte.
Du durchläufst die Schleife und erzeugst darin das SQL-Statement. Das Schleifenende ist erreicht, wenn der Code nicht mehr eingerückt ist, also bei dem try. Der Code dahinter ist kein Teil der Schleife mehr. Du erzeugst also x-mal ein SQL-Statement, schickst aber erst nach Beendigung der Schleife das dann aktuelle Statement ab.
Brooklyn
User
Beiträge: 5
Registriert: Montag 11. Januar 2010, 08:16

Du durchläufst die Schleife und erzeugst darin das SQL-Statement. Das Schleifenende ist erreicht, wenn der Code nicht mehr eingerückt ist, also bei dem try. Der Code dahinter ist kein Teil der Schleife mehr. Du erzeugst also x-mal ein SQL-Statement, schickst aber erst nach Beendigung der Schleife das dann aktuelle Statement ab.
Klingt nach Deiner Erkläung einleuchtend! Also heißt das im Klatext, das ich quasi nach jedem SQL-Statement ein cursor.execute(sql) u. ausführen muß um das zu vor durch die For-Schleife erstellte SQL-Statment wirksam zu machen?
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Brooklyn hat geschrieben:Klingt nach Deiner Erkläung einleuchtend! Also heißt das im Klatext, das ich quasi nach jedem SQL-Statement ein cursor.execute(sql) u. ausführen muß um das zu vor durch die For-Schleife erstellte SQL-Statment wirksam zu machen?
Ja.

Um eine Datenbankaktivität durchzuführen musst du natürlich eine entsprechende Funktion aufrufen die sich mit der Datenbank unterhält. In diesem Fall ist das das execute(). Du kannst den String sql so viel wie du willst befüllen, entscheidend ist das was drin steht wenn du das Statement ausführst.

Das commit() kann natürlich gerne ganz zum Schluss nach der Schleife kommen.
Brooklyn
User
Beiträge: 5
Registriert: Montag 11. Januar 2010, 08:16

Danke für Deine Hilfe und für Deine Denkanstöße!

Man kann sich manchmal den Kopf zerbrechen auch wenn die Lösung sehr nahe liegt. :D

Code: Alles auswählen

try:    
    for row in reader:
        comp = row[0]
        user = row[1]
        mail = row[4]

        data = [ comp, user, mail ]
        sql = ("INSERT INTO usermail (comp, user, mail) VALUES ( ?, ?, ? )")
        cursor.execute(sql, data)

except:
    print ("ERROR: Can´t insert data")

connection.commit()
Antworten