csv in nächste spalte schreiben

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
Kombifahrer
User
Beiträge: 8
Registriert: Montag 5. Mai 2014, 23:16

Hallo,
ich hab folgende Aufgabe zu lösen, ich möchte aus zwei verschiedenen Dateien bestimmte werte auslesen, die ich in einer csv Tabelle speichern will,
und zwar bin ich soweit das ich eine Datei auslese, diese in einer csv in Spalte A und B speichere (Zeilen ca. 200),
aber die Daten aus der zweiten Datei bekomme ich nicht in die spalten C und D, wie kann ich das bewerkstelligen?
Hintergrund ist das ich die Deltas aus den Werten in B2 und D2, B3 und D3 usw. ich Excel weiterverarbeiten will.

z.B. so:
B2 ; D2
10 - 8 = 2

der absolute burner wäre es wen ich diese als .xlsx speichern könnte um die Daten später mit Makros zu bearbeiten.
naja das ist glaub ich noch Zukunftsmusik oder kann man diese Ausbau stufe hierbei gleich berücksichtigen??

Code: Alles auswählen

import os.path
verz="verz"
def extract_value(line):
    return line.split('/')[1].strip().replace('.', ',')

for dat in os.listdir(verz):
    if dat.endswith(".txt") :
        with open(os.path.join(verz, dat)) as lines:
            name=dat
            code=(name.split('.')[0][-4:])
            try:
                int(code)
            except:
                continue
            datei=open(verz+name+".csv","w")
            datei.write(name+"\n")
            for line in lines:
                if 'K1/' in line:
                    zeile = extract_value(line)
                    try:
                        wert=zeile.split(' ')[1]
                    except:
                        wert=''
                    nr=zeile.split(' ')[0]
                    datei.write(nr+';'+wert+"\n")
        name2=name.split('.')[0]+'_zweite_datei.txt'
        if name2 in os.listdir(verz):
            datei.close()
            with open(os.path.join(verz, name2)) as lines:
                datei=open(verz+name+".csv","a+")
                datei.write(';'+';'+name2+"\n")
                for line in lines:
                    if 'K1/' in line:
                        zeile = extract_value(line)
                        try:
                            wert=zeile.split(' ')[1]
                        except:
                            wert=''
                        nr=zeile.split(' ')[0]
                        datei.write(';'+';'+nr+';'+wert+"\n")
    datei.close()   
BlackJack

@Kombifahrer: Ich weiss nicht ob ich wirklich verstanden habe was die Frage ist, was vielleicht auch an diesem furchtbar wirren Code liegen könnte. Das ist deutlich zu viel was da auf einmal passiert, sowohl von der reinen Code-Menge als auch das da alles mögliche vermischt ist. Simpelste Trennung bei solchen Programmen ist es Eingabe, Verarbeitung, und Ausgabe voneinander zu trennen.

Wenn ich mal raten müsste was Du da versuchst: Man kann nicht nachträglich zusätzlich etwas an Zeilen anfügen ohne die alten Zeilen zu lesen, die Daten anfügen und dann wieder schreiben. Wenn Du eine CSV-Datei mit zwei Spalten hast, dann kannst Du nicht zusätzliche Spalten hinzufügen in dem Du weitere Zeilen hinter die bereits vorhandenen speicherst. Das heisst Du musst entweder Code schreiben der die alten Daten liest, erweitert, und neu schreibt, oder das ursprüngliche Programm schon so schreiben, dass eine Zeile erst dann geschrieben wird, wenn alle Daten dafür komplett vorliegen.

Versuch mal bessere Namen zu finden. Und keine Abkürzungen wenn die nicht allgemein geläufig sind. `verz` und `dat` sind das nicht.

Für CSV-Dateien gibt es in der Standardbibliothek das `csv`-Modul. Selbst wenn es das nicht gäbe würde man die Zeichenketten nicht mit ``+`` zusammen setzen. Dafür gäbe es die `join()`-Methode auf Zeichenketten.

Für das erste `os.listdir()` und das ``if`` in der Schleife könnte man das `glob`-Modul verwenden.

Der Code ist auch ein wenig verwirrend. Versuch mal ``continue`` komplett zu vermeiden. Und auf jeden Fall nackte ``except:`` ohne eine konkrete Ausnahme anzugeben. Damit kannst Du Dir das Leben wirklich sehr schwer machen wenn irgendwo eine Ausnahme auftreten sollte mit der Du *nicht* gerechnet hast. In der Regel ist die Behandlung einer Ausnahme nicht das richtige für *jede* Ausnahme, solange man die nicht mindestens protokolliert, damit sie nicht übersehen werden kann.

In der Schleife steht zwei mal fast identischer Quelltext. Das verletzt das „Don't Repeat Yourself”-Prinzip (DRY). Für so etwas gibt es Funktionen. Davon solltest Du deutlich mehr verwenden.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du musst musst eben die Informationen aus den Dateien lesen, diese zusammenführen und anschließend zusammen schreiben. Am einfachsten ist es wenn du alles in einer Liste sammelst.

Allerdings solltest du deinen Code gründlich überarbeiten. Der ist fehlerhaft, umständlich und total unverständlich. Ich fange mal von oben nach unten an, dann siehst du auch, was du besser machen kannst.

Schau dir PEP 8 an, das ist der Style-Guide von Python. Wenn du Code in Python schreibst, dann solltest du dich daran halten. Dann wird dein Code nicht nur einheitlich, auch andere, wie wir, können ihn dann leichter lesen. Bei der Gelegenheit solltest du dich auch gleich für eine Sprache entscheiden, Englisch oder Deutsch. Beides vermischt ist ein wenig gruselig. Vorzugsweise solltest du natürlich nur englische Namen verwenden, dann kann es auch jeder verstehen.

Auch solltest du vernünftige und *aussagekräftige* Bezeichner wählen. "verz" ist nicht viel kürzer als "verzeichnis", dafür muss der Benutzer aber über dessen Bedeutung raten. Das Problem ist hier aber noch tiefer. Du hast total generische Namen. "verz", "datei", "name", "code", "wert", das könnte für alles mögliche stehen. Wichtig ist *was* für eine Datei, *was* für ein Name, *was* stellt der Wert dar.

Es gibt ein csv-Modul, dann musst du das ganze Auslesen und Schreiben der Dateien nicht selber machen. Dann werden auch gleich alle möglichen Randfälle und Besonderheiten umgesetzt, an die du alle nicht gedacht hast.

Schreibe Funktionen, dann kannst du deinen Code auch wiederverwenden und in sinnvolle Strukturen unterteilen. Du hast da nur einen riesigen Block aus cryptischem Code, ohne jegliche Kommentare. Es ist überhaupt nicht ersichtlich was dein Programm macht, da müsste man sich jetzt ewig ransetzen und lesen. Wenn du deinen Code in ein paar Wochen noch einmal rausholen solltest, dann wird es dir ganz genau so gehen, obwohl du ihn selbst geschrieben hast.

Wenn du Dateien mit einer bestimmten Endung suchst, dann solltest du das glob-Modul verwenden. Dann sparst du dir das ganze händische Filtern. Auch solltest du nur einen Aufruf von os.listdir haben, zwei Stück sind hier irgendwie überflüssig. Der ganze Aufbau ist so oder so ein wenig mysteriös, ich verstehe nicht, was da nun passieren soll oder wie viele txt-Dateien da überhaupt vorkommen können.

"lines" in Zeile acht sind keine Zeilen. Zu dem Zeitpunkt wurde noch gar nichts gelesen. Du hast zu diesen Zeitpunkt nicht mehr als ein Dateiobjekt. Was glaubst du, was Zeile 9 macht? Versuche die Frage mal zu beantworten, wahrscheinlich hast du hier etwas Grundlegendes nicht verstanden.

Die Klammern in Zeile 10 sind überflüssig, das except in Zeile 13 einfach nur gefährlich. Damit werden wirklich *alle* Fehler abgefangen, auch Programmierfehler. Zähle bei einem except immer die Ausnahmen auf, die du auch wirklich behandeln kannst.

Dateien solltest du mittels with-Statement öffnen, dann werden sie auch garantiert wieder geschlossen. Das Schließen der Datei in Zeile 41 hängt außerhalb des if-Statements. Unter Umständen versuchst du da einen Datei zu schließen, die du nie geöffnet hast. Strings solltest du nicht mittels + zusammensetzen, sondern mittels String Formatting. Dann kann man das auch vernünftig lesen. Zeilen 15 bis 25 und 29 bis 30 sind quasi identisch. Benutze funktionen.

Benutze Konstanten oder berechne Werte. Die diversen -4 oder K1 stehen einfach so im Code rum, da weißt du bald schon selbst nicht mehr, was diese bedeuten.

Die Zeilen 20 bis 23 sind schon wieder so ein gefährliches Konstrukt. Da könnte alles Mögliche schief gehen und dein Programm in einen ungültigen Zustand versetzen.

Da ließen sich jetzt noch überall weitere Kleinigkeiten finden, das sind aber zunächst die groben Sachen. Das solltest du als erstes mal beheben, besonders die Unterteilung in Funktionen. Sonst braucht man gar nicht mehr Hand einen deinen Code anlegen. Das ist alles viel zu fragil.
Das Leben ist wie ein Tennisball.
BlackJack

@EyDu: Also ich hätte das in Zeile 8 auch `lines` genannt denn es wird als „iterable of lines” verwendet, was es auch tatsächlich ist. Wäre vielleicht deutlicher wenn der Code zwischen dem öffnen und dem iterieren nicht durch den ganzen Code dazwischen ”unterbrochen” wäre der *nach* dem öffnen der Datei erst prüft ob man die *überhaupt verarbeiten will* — und zwar ohne das irgend etwas aus der Datei dazu benötigt wird.
BlackJack

@Kombifahrer: Komplett ungetestet und versucht zu erraten was der Code in Deinem Beitrag machen soll:

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import absolute_import, division, print_function
import csv
import os
import re
from itertools import izip

FILENAME_REGEX = re.compile(r'\d{4}\.txt$')


def iter_filename_pairs(path):
    paths_a = (
        os.path.join(path, filename)
        for filename in os.listdir(path)
        if FILENAME_REGEX.search(filename)
    )
    paths_b = (
        os.path.splitext(path)[0] + '_zweite_datei.txt' for path in paths_a
    )
    return ((a, b) for a, b in izip(paths_a, paths_b) if os.path.exists(b))


def parse_file(filename):
    with open(filename) as lines:
        for line in  lines:
            if 'K1/' in line:
                number, _, value = (
                    line.split('/')[1].strip().replace('.', ',').partition(' ')
                )
                yield [number, value]


def main():
    base_path = 'verzeichnis'
    filename_pairs = iter_filename_pairs(base_path)
    for filename_a, filename_b in filename_pairs:
        with open(os.path.splitext(filename_a)[0] + '.csv', 'w') as csv_file:
            writer = csv.writer(csv_file, delimiter=';')
            writer.writerows(
                a + b
                for a, b in izip(parse_file(filename_a), parse_file(filename_b))
            )


if __name__ == '__main__':
    main()
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Kombifahrer hat geschrieben:der absolute burner wäre es wen ich diese als .xlsx speichern könnte
https://pypi.python.org/pypi/openpyxl
Antworten