Einlesen eines csv-Files

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
triac
User
Beiträge: 2
Registriert: Mittwoch 22. Mai 2013, 09:50

Hallo Leute,

das ist mein erster Beitrag in eurem Forum daher möchte ich mich kurz vorstellen.
Ich bin 27 Jahre alt und komme aus Österreich. Mit Python beschäftige ich mich erst seit kurzem.
Größtenteils werde ich es benötigen um Abläufe in der 3D-Software Blender zu automatisieren.

Da ich im Blender-Forum leider nicht weiter komme wende ich mich jetzt an euch - passend zu dem Spruch "Geh gleich zum Schmied und nicht zum Schmiedl" :wink:

Nun zum eigentlichen Grund:
-Ich möchte ein csv-File importieren und ablegen (in einer Datenbank/Liste/...)
-danach muss ich auf jede einzelne Zelle zugreifen können

Meine Fragen:
-ist eine Datenbank sinnvoll? SQL?
-wie kann ich danach auf die einzelnen Zellen zugreifen?

Zusatz:
-in manchen "Zellen" stehen tatsächlich Zeilenumbrüche (so sieht es zumindest in Excel aus - Screenshot anbei) wie bekomme ich auch diese Formatierung bei der Ausgabe hin?

Bild

Bis jetzt habe ich versucht alles in einzelne Listen zu speichern, das erscheint mir allerdings nicht sehr sinnvoll - trotzdem anbei auch noch meinen "alten" Ansatz:

Code: Alles auswählen

fileO = open('F://Test.csv','r',encoding='LATIN1')

csvreader=csv.reader(fileO, delimiter=';')

p_model= []
p_weight = []
p_image = []
p_desc_de = []
p_desc_de_test = []
p_cat_0 = []
p_cat_1 = []
p_cat_2 = []
gm_min_order = []

for row in csvreader:
    if len(row) > 1:
        p_model.append(row[2])
        p_weight.append(row[13])
        p_image.append(row[15])
        p_desc_de_test.append(row[19])
        p_cat_0.append(row[20])
        p_cat_1.append(row[21])
        p_cat_2.append(row[22])
        gm_min_order.append(row[23])

def Daten(i):

    print('p_model: ' + p_model[i])
    print('p_weight: ' + p_weight[i])
    print('p_image: ' + p_image[i])
    print('p_desc_de_test: ' + p_desc_de_test[i])
    print('p_cat_0: ' + p_cat_0[i])
    print('p_cat_1: ' + p_cat_1[i])
    print('p_cat_2: ' + p_cat_2[i])
    print('gm_min_order: ' + gm_min_order[i])
    
Daten(1)
Gibt es vielleicht ein Beispielscript?

Schon mal Danke im Voraus!!

PS: Es handelt sich bei der Liste um mehrere 1000Positionen, daher muss alles automatisiert gehen
Zuletzt geändert von Anonymous am Mittwoch 22. Mai 2013, 10:28, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Hi und willkommen im Forum!

Hast du schon das eingebaute Python Paket "csv" gefunden? Du bist ja nicht der erste mit diesen Herausforderungen, und dort finden sich viele übliche Hilfsmittel gesammelt. Beispiel:

Code: Alles auswählen

>>> import csv
>>> with open('eggs.csv', 'rb') as csvfile:
...     spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
...     for row in spamreader:
...         print ', '.join(row)
Spam, Spam, Spam, Spam, Spam, Baked Beans
Spam, Lovely Spam, Wonderful Spam
Ich bin mir nicht ganz sicher, wie du Zeilenumbrüche in einer einzelnen Zelle hinbekommst. Vielleicht schaust du dir die CSV Datei mal in einem reinen Texteditor an. Excel macht da gerne kleine Änderungen beim Öffnen und Anzeigen.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
triac
User
Beiträge: 2
Registriert: Mittwoch 22. Mai 2013, 09:50

Das eingebaute csv-package habe ich schon gefunden. ja.

Mit Zeilenumbruch meine ich tatsächlich - wenn ich das csv-File im Text-Editor Öffne folgendes:

Genauso wenn ich mir das in Excel öffne sehe ich in einer Zelle folgendes stehen:
###################################
STACKER-DESTACKER 9640Kit + Netzteil
2 SAT-Anschlsse mit terr. Signal ber 1 Kabel
Voraussetzungen: (GA beachten)
- digitaltaugliches KOAX-Kabel!
- Kabelweg 7 bis max. 70m
Frequenzbereich: 5-3550MHz
DiSEqC: ToneBurst (Mini-DiSEqC)
Anwendungsbeispiele:
- Single auf TWIN Umrstung ber ein bestehendes
Kabel, wenn keine M”glichkeit besteht ein 2. Kabel
nachzuziehen
- anstatt nur 1 Anschluá von einem Multischalter
auf 2 erweitern (ber nur 1 Kabel!)
unkomplizierter Umbau!

Kurzschlsse unbedingt vermeiden! (sonst keine Garantie!)

Vorsicht bei Anwendungen mit D-BOX
#############################

ausgegeben wird dann aber (logischerweise) nur:

"STACKER-DESTACKER 9640Kit + Netzteil"

-ist eine Datenbank dafür sinnvoll? SQL? Wie gehe ich das am besten an?
-wie kann ich danach auf die einzelnen Zellen zugreifen?/in der Datenbank
BlackJack

@triac: Ob eine Datenbank sinnvoll ist und welche hängt ganz davon ab, was Du überhaupt machen möchtest. Wenn die CSV nicht so gross ist, dass sie den Arbeitsspeicher sprengt, und Du die Daten als zweidimensionale Datenstruktur benötigst, dann ist die CSV selbst vielleicht schon genug. Wenn Du die mit dem `csv`-Modul aus der Standardbibliothek in eine Liste einliest, dann hast Du eine Liste mit Listen die jeweils die Zelleninhalte einer Zeile enthalten. Da kann man dann über die Koordinaten wahlfrei auf jede Zelle zugreifen.

Je nach dem wie das Zugriffsmuster auf die Daten dann tatsächlich aussieht, kann es Sinn machen die Daten in anderen Datenstrukturen zu organisieren. Oder vielleicht sogar in einer Datenbank abzulegen. Ohne zu wissen was mit den Daten passieren soll, kann man da aber nichts weiter zu sagen.

Ad Zusatz: Zellen in CSV-Dateien können Zeilenumbrüche enthalten. Damit kommt das CSV-Modul klar. Da sind im Zelleninhalt, was ja Zeichenketten sind, dann die entsprechenden Zeilenumbruchszeichen enthalten.

Im Bildschirmfoto sieht man übrigens, das die Daten mit einer falschen Kodierungsangabe in die Tabellenkalkulation importiert wurden.

Die zusammengehörigen Daten aus einer Zeile in „parallele” Listen zu speichern ist keine gute Idee. Das macht den Quelltext unnötig kompliziert und fehleranfällig. Zusammengehörige Daten sollten auch zusammen in einem Objekt gespeichert werden. Hier würde sich eine Liste anbieten, oder ein `collections.namedtuple`, oder ein Wörterbuch (`dict`) pro Zeile. Oder ein eigener Datentyp, falls da noch irgendwie Verhalten zum Zustand für die Datensätze hinzu kommt.

Funktionen sollten auf nichts zugreifen was nicht als Argument übergeben wurde, mal abgesehen von Konstanten. Also die `Daten()`-Funktion sollte nicht einfach so auf die ganzen Listen zugreifen können. Das schafft unnötige und schwer durchschaubare Abhängigkeiten im Quelltext. Dazu verbannt man am besten alles was nicht Konstanten, Funktionen, oder Klassen definiert von der Modulebene in Funktionen. Dann kommt man gar nicht erst in Versuchung in einer Funktion etwas zu benutzen was nicht als Argument übergeben wurde.

Dateien sollte man auch wieder schliessen. Sehr zuverlässig geht das mit der ``with``-Anweisung.

Bei Namen sollte man nicht gebräuchliche Abkürzungen, komische Prä- und Postfixe, und durchnummerieren vermeiden. Wenn man anfängt zu nummerieren, möchte man in der Regel eine geeignete Datenstruktur verwenden. Zum Beispiel eine Liste oder ein Tupel.

Edit: Ungetestet:

Code: Alles auswählen

import csv
from collections import namedtuple

# 
# TODO: Find a better name for this type.
#       
Record = namedtuple(
    'Record', 'model weight image description_test categories min_order'
)
INDICES = [2, 13, 15, 19, slice(20, 23), 23]

assert len(Record._fields) == len(INDICES)


def main():
    with open('F://Test.csv', 'r', encoding='latin1') as csv_file:
        records = [
            Record(*(row[i] for i in INDICES))
            for row in csv.reader(csv_file, delimiter=';')
            if len(row) >= 24
        ]
    print records[1]  # Attention: Prints the *second* record!


if __name__ == '__main__':
    main()
Antworten