Seite 1 von 1

Liste, Dictionary oder Kombination - was hierfür richtig?

Verfasst: Donnerstag 3. Juli 2008, 19:59
von SchaubFD
Hallo,

ich habe öfters folgendes Problem. Ich muss Daten aus verschiedenen Quellen (Dateien) verbinden, möchte aber auf Datenbanken verzichten, da die Datenmengen unproblematisch für Skriptsprachen sind. Teilweise sind es zusammengesetzte Schlüsselwerte wie z.B. im folgenden Beispiel Kostenträger und Kostenstelle. Bisher habe ich dies über einen String mit festen Längen gemacht z.B. '0013_4700'' als Key. Wie würdet ihr solche Probleme angehen. Ich möchte den Code kompakt und trotzdem sehr lesbar halten.

Folgendes Beispiel ist einfach mal so zusammengesetzt und kann durchaus Fehler enthalten! Es soll auch als Beispiel für andere Forenteilnehmer dienen, die ähnliches machen.

Code: Alles auswählen

# -*- coding: utf-8 -*-
# Quellcode im Unicode Zeichensatz

# Telefonliste Vorname, Nachname, Telefon
telefon=[]
telefon.append(['Ingo','Meier','132'])
telefon.append(['Paul','Schmitt','342'])
telefon.append(['Ute','Meier'],'105')
telefon.append(['Peter','Schmidt','311'])

# Abteilung Abteilung, Kostenstelle, Kostenträger
abteilung=[]
abteilung.append('2','4800','11')
abteilung.append('1','4700','13')

# Zuordnung Abteilung, Teiefon
zuordnung=[]
zuordnung.append('1'.'311')
zuordnung.append('1'.'342')
zuordnung.append('2'.'132')
zuordnung.append('2'.'105')

# Gesprächskosten
kosten=[]
kosten.append('105','34,50']
kosten.append('132','12,34']
kosten.append('311','15,67']
kosten.append('342','10,10']

# Ziel der Auswertung
# Eine Liste sortiert nach Abteilung, Kostenträger, Kostenstelle
# mit Auflistung der Telefonnutzer je Abteilung sortiert
# nach Nachname, Vorname. Es werden alle Felder in der
# Ausgabe ausgegeben. Die Daten sollen später in eine CSV Datei.

Ausgabe:
-----------------------------------------------------------
'1','13','4700','Schmidt','Peter','311','15,67'
'1','13','4700','Schmitt','Paul' ,'342','10,10'
'2','11','4800','Meier'  ,'Ingo' ,'132','12,34'
'2','11','4800','Meier'  ,'Ute'  ,'105','34,50'

Verfasst: Donnerstag 3. Juli 2008, 20:05
von EyDu
Wenn du keine Datenbank installieren willst, dann nimm doch SQLite. Das ist viel flexibler und weniger fehleranfällig als eine eigene Lösung.

Verfasst: Donnerstag 3. Juli 2008, 20:07
von DasIch
Dictionaries?

Verfasst: Donnerstag 3. Juli 2008, 20:31
von CM
Das richt geradezu nach dicts. Das [mod]shelve[/mod]-modul könnte auch was für Dich sein.

Verfasst: Donnerstag 3. Juli 2008, 20:58
von BlackJack
Ich würde hier auch `sqlite` empfehlen. Wenn Dictionaries mit zusammengesetzten Schlüsseln, dann würde ich aber Tupel als Schlüssel nehmen und nicht mit Zeichenketten operieren. Überhaupt sollte man die Zahlen, die als Zahlen behandelt werden sollen auch als solche verarbeiten. Sonst bekommt man beim Sortieren schnell Probleme wenn "Zeichenkettenzahlen" alphabetisch und nicht nach ihrem numerischen Wert sortiert werden.

Verfasst: Donnerstag 3. Juli 2008, 22:05
von SchaubFD
Kurze Zwischenfrage, wo finde ich eine Kurzübersicht/Dokumentation zu SQLight am besten mit Python Beispielen?

Ich möchte halt nicht Oracle, SQL-Server oder Access einsetzen, da man sich dann immer fest an etwas bindet oder Treiber/ODBC dazu notwendig wären. Natürlich wären geschachtelte SQL Abfragen dabei sinnvoller. Es soll möglichst übersichtlich bleiben.

Wenn dieses SQLight gut sein sollte, dann könnte ich mir den Aufwand selbst gestrickter Strukturen sparen.

Verfasst: Donnerstag 3. Juli 2008, 22:12
von Karl
SchaubFD hat geschrieben:Kurze Zwischenfrage, wo finde ich eine Kurzübersicht/Dokumentation zu SQLight am besten mit Python Beispielen?

Ich möchte halt nicht Oracle, SQL-Server oder Access einsetzen, da man sich dann immer fest an etwas bindet oder Treiber/ODBC dazu notwendig wären. Natürlich wären geschachtelte SQL Abfragen dabei sinnvoller. Es soll möglichst übersichtlich bleiben.

Wenn dieses SQLight gut sein sollte, dann könnte ich mir den Aufwand selbst gestrickter Strukturen sparen.
Ich hab's zwar noch nicht eingesetzt aber erstens mal heißt es SQLite, nicht light ;)
2. Die Syntax ist wohl einfach die normale SQL-Syntax wie zum Beispiel bei MySQL auch, ansonsten schau mal hier:
http://www.sqlite.org/lang.html
Wo du Pythonbeispiele findest, weiß ich nicht aber Google hat da bestimmt was ;)

Verfasst: Donnerstag 3. Juli 2008, 22:20
von DasIch
Ich würde in diesem Falle wohl Elixir o.ä. einsetzen.

Verfasst: Freitag 4. Juli 2008, 08:59
von lutz.horn
SchaubFD hat geschrieben:Kurze Zwischenfrage, wo finde ich eine Kurzübersicht/Dokumentation zu SQLight am besten mit Python Beispielen?
Ich habe Dein Problem mal kurz mit SQLite implementiert. Zuerst musst Du die Struktur der Datenbank anlegen. Die DDL-Statemenst könnten z. B. so aussehen (Datei telefon-ddl.sql):

Code: Alles auswählen

create table telefon (telefonnummer integer not null primary key,
                      vorname string not null,
                      nachname string not null);

create table abteilung (id integer primary key,
                        kostenstelle integer not null,
                        kostentraeger integer not null);

create table abteilung_telefon (abteilung_id integer not null,
                                telefon_id integer not null);

create table kosten (telefon_id integer not null,
                     kosten double);
Um mit dem sqlite-Binary die Datenbank zu erzeugen, reicht

Code: Alles auswählen

$ sqlite3 telefon.sqlite3 < telefon-ddl.sql
Dann erzeugt dieser Python-Code die gewünschte CSV-Datei.

Code: Alles auswählen

# -*- coding:utf8 -*-

import sqlite3
import csv

connection = sqlite3.connect("telefon.sqlite3")

insert_sql = "insert into telefon values (? ,?, ?)"
connection.executemany(insert_sql, [(132, "Ingo", "Meier"),
                                    (342, "Paul", "Schmitt"),
                                    (105, "Ute", "Meier"),
                                    (311, "Peter", "Schmidt")])

insert_sql = "insert into abteilung values (?, ?, ?)"
connection.executemany(insert_sql, [(2, 4800, 11),
                                    (1, 4700, 13)])

insert_sql = "insert into abteilung_telefon values (?, ?)"
connection.executemany(insert_sql, [(1, 311),
                                    (1, 342),
                                    (2, 132),
                                    (2, 105)])

insert_sql = "insert into kosten values (?, ?)"
connection.executemany(insert_sql, [(105, 34.50),
                                    (132, 12.34),
                                    (311, 15.67),
                                    (342, 10.10)])

connection.commit()

cursor = connection.execute("""
select abteilung.id, abteilung.kostentraeger, abteilung.kostenstelle,
       telefon.nachname, telefon.vorname, telefon.telefonnummer,
       kosten.kosten
from abteilung, abteilung_telefon, telefon, kosten
where abteilung.id = abteilung_telefon.abteilung_id
  and telefon.telefonnummer = abteilung_telefon.telefon_id
  and kosten.telefon_id = telefon.telefonnummer
order by abteilung.id, telefon.nachname, telefon.vorname;""")

writer = csv.writer(open("telefon.csv", "w"))
writer.writerow(["Abteilung", "Kostenträger", "Kostenstelle", "Nachname",
                "Vorname", "Telefon", "Kosten"])
writer.writerows(cursor.fetchall())
Ergebnis is telefon.csv:

Code: Alles auswählen

Abteilung,Kostenträger,Kostenstelle,Nachname,Vorname,Telefon,Kosten
1,13,4700,Schmidt,Peter,311,15.67
1,13,4700,Schmitt,Paul,342,10.1
2,11,4800,Meier,Ingo,132,12.34
2,11,4800,Meier,Ute,105,34.5

Verfasst: Freitag 4. Juli 2008, 09:59
von SchaubFD
Hallo Lutz,

DANKE!

... deine Antwort macht mich fast sprachlos! Ich bin gleich aus zwei Gründen sehr erfreut darüber. Zu einem Teil, ich habe nicht mit einer kompletten Lösung gerechnet. Zum anderen Teil, deine Antwort beantwortet mir eine Frage, die ich noch stellen wollte (massiges aufrufen von SQL Befehlen bremst). Zudem ist es auch ein schönes Beispiel für sqlite (jetzt richtig geschrieben)

Ich hoffe in naher Zukunft auch mal so gut helfen zu können.

Verfasst: Freitag 4. Juli 2008, 10:13
von lutz.horn
SchaubFD hat geschrieben:Zu einem Teil, ich habe nicht mit einer kompletten Lösung gerechnet. Zum anderen Teil, deine Antwort beantwortet mir eine Frage, die ich noch stellen wollte (massiges aufrufen von SQL Befehlen bremst).
Gern geschehen.

Was ich nicht berücksichtigt habe, ist z. B. referentielle Integrität über Fremdschlüssel. Dazu gibt es zwar eine SQL-Syntax, die aber von SQLite ignoriert wird. Es ist deswegen möglich, in die von mir beschriebenen Tabellen z. B. Kosten einzutragen, die auf eine nicht existierende Telefonnummer verweisen.

Das Schöne an SQL mit Python ist, dass die beteiligten Konzpete und Klassen in der Python Database API Specification v2.0 datenbankunabhängig spezifiziert werden. Du kannst also zumindest den Python-Code auch mit einer MySQl-Datenbank verwenden, für die allerdings die DDL-Statements anzupasen wären.