Länge von DictReader Instanz

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
Benutzeravatar
martinjo
User
Beiträge: 189
Registriert: Dienstag 14. Juni 2011, 20:03

Hallo

Ich komme bei einem Skript nicht weiter.

Code: Alles auswählen

import sys, csv
...
csv_reader_shipments_all = csv.DictReader(input_file)
for line in csv_reader_shipments_all:
    print line
Soweit ist alles ok, jetzt möchte ich aber zuvor noch die Länge von csv_reader_shipments_all ausgeben.

Nutze ich dazu len(list(csv_reader_shipments_all)) führt das dazu, dass csv_reader_shipments_all durchlaufen wird und "for line in" nicht mehr funktioniert.

Mein erster Lösungsversuch habe ich ergoogelt und den Hinweis gefunden, mit seek den CSV_Reader zurückzusetzen:
AttributeError: DictReader instance has no attribute 'seek'

Beim zweiten Versuche wollte ich eine Kopie der Instanz anlegen, was aber anscheinend nichts bringt, da auf das selbe Objekt? verwiesen wird. Das bedeutet ist die Kopie durchgelaufen ist auch das Original durchgelaufen?
Das sind aber auch nur Vermutungen.

Hier noch der Namensraum meines DictReader welcher kein seek besitzt:

Code: Alles auswählen

['__doc__', '__init__', '__iter__', '__module__', '_fieldnames', 'dialect', 'fieldnames', 'line_num', 'next', 'reader', 'restkey', 'restval']
Meine Fragen nun, warum habe ich kein seek und wie mache ich das sonst am besten wenn ich nicht in der Schleife erst zählen will?

Danke
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

``DictReader`` arbeitet auf einer Datei und den Pointer dieser Datei willst du zuruecksetzen:

Code: Alles auswählen

In [1]: import csv

In [2]: f = open('tmp/test.csv')

In [3]: for line in csv.DictReader(f):
   ...:     print line
   ...:     
{'baz': '3', 'foo': '1', 'bar': '2'}
{'baz': '6', 'foo': '4', 'bar': '5'}

In [4]: f.seek(0)

In [5]: for line in csv.DictReader(f):
    print line
   ...:     
{'baz': '3', 'foo': '1', 'bar': '2'}
{'baz': '6', 'foo': '4', 'bar': '5'}
Was deine Kopie-Vermutungen angeht: Das kommt darauf an, wie du deine Kopie erstellst. In dem Fall hier ist die Ursache aber, dass der Zustand in dem Datei-Objekt steckt und nicht im Reader.

Zu guter letzt: Was willst du denn eigentlich machen?
Benutzeravatar
martinjo
User
Beiträge: 189
Registriert: Dienstag 14. Juni 2011, 20:03

Danke

Das mit dem neu setzen des Pointers wollte ich vermeiden, da dies in einer anderen Funktion geschieht:

Code: Alles auswählen

# read all shipments
def read_csv_input_file(csv_file):
    input_file = codecs.open(csv_file, "rb")
    csv_reader = csv.DictReader(input_file, delimiter=';')
    return csv_reader

Code: Alles auswählen

def seperate_shipments(csv_reader_shipments_all):0
    #csv_reader_shipments_all_len = len(list(copy.copy(csv_reader_shipments_all_copy)))
    shipments_all_1 = []
    shipments_all_2 = []
    for line in csv_reader_shipments_all:
            if line["Pickup Company"] == "company1":
                shipments_all_1.append(line)
            else:
                shipments_all_2.append(line)
    print "shipments 1 =\t %s" % len(shipments_all_1)
    print "shipments 2 =\t %s" % len(shipments_all_2)
Benutzeravatar
martinjo
User
Beiträge: 189
Registriert: Dienstag 14. Juni 2011, 20:03

also ich habe die input_file in der ersten Funktion nun global definiert, so kann ich die Datei auch in der zweiten Funktion zurücksetzen, nicht schön aber ich bin ja noch Anfänger und darf das^^
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Eine Alternative waere auf einer Liste des DictReader-Iterators zu arbeiten, statt auf dem Iterator selbst. Das hat aber zur folge, dass du die Datei komplett einliest und CSV-Dateien haben ja die Neigung zu wachsen ...

Eine weitere waere das Nachzaehlen von ``enumerate`` erledigen zu lassen.

Es ist zwar schoen, dass du deinen Code in kleine Funktionen zerlegst, aber `read_csv_input_file` tut reichlich wenig und schlimmer noch: Sie verbaut dir jeglichen sinnvollen Umgang mit der Datei, inklusive sie zu schliessen, wenn du fertig bist.

Aber wenn du nicht damit herausruecken willst, was du eigentlich vorhast ...
Benutzeravatar
martinjo
User
Beiträge: 189
Registriert: Dienstag 14. Juni 2011, 20:03

He, ich dachte was ich damit Vorhabe ist mit dem Code welchen ich als letztes gepostet habe ersichtlich, ich will einfach nur 2 Listen erstellen damit ich die Anzahl der Shipments pro Company habe :D und damit habe ich dann halt noch ein wenige experimentiert.

Bisher hatte ich immer das Problem, dass ich zu wenig Funktionen erstellt habe und später viel zu oft doppelten Code drin hatte, bei diesem Skript mal wollte ich das mal von Anfang an richtig machen.

Aber ich glaube ich komme nun zurecht, der Hinweis, dass es eben die Datei und nicht die CSV_Reader Instanz ist hat mir geholfen, Danke nochmal!
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Naja das zeigt was du machst, aber nicht was dein Ziel ist.

Wenn ich dich frage wohin du laeufst, ist die passende Antwort ja auch nicht "bis zur naechsten Kurve", wenn du eigentlich in die naechste Stadt willst ;)
Antworten