Messwerte auslesen und in neue Datei 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
leooonidas
User
Beiträge: 2
Registriert: Montag 15. Juli 2019, 10:03

Hallo Zusammen,

ich möchte mit python eine txt-Datei auslesen und die Daten daraus, geordnet in neuen txt-Dateien speichern.
Das Auslesen klappt ohne Probleme, aber beim Schreiben in die neuen Dateien habe ich Probleme.
Ich bekommen beim ausführen des folgenden Codes:

Code: Alles auswählen

#Daten auslesen
a = open('test.txt', 'r')
lines = a.readlines()
a.close()

#Liste der Messzeitpunkte erstellen
TimesOfMeasurement = []
for line in lines[1:]:
    a = line.split()
    time = a[1]
    TimesOfMeasurement.append(time)

#Anzahl der Messzeitpunkte
x = len(TimesOfMeasurement)
NumberOfMeasurements = range(1, x+1)

#Die verschiedenen auszulesenden Messdaten
KindsOfMeasurement = ['RC' , 'Dnear', 'Dfar']

#Dictionary für jede Messart erstellen
i = 8
n = len(lines)
Measurements = {}
for Kind in KindsOfMeasurement:
    i = i + 1
    Measurements[Kind]=[]
    for line in lines[1:n-1]:
        a = line.split()
        val = a[i]
        Measurements[Kind].append(val)
        

#Wertepaare in Dateien schreiben
for Kind in KindsOfMeasurement:
    f = open(Kind+'.txt', 'w')
    for k in range(len(TimesOfMeasurement)):
        f.write('%g\n' % (Measurements[Kind][k]))
    f.close()
    
diese Fehlermeldung:

Code: Alles auswählen

TestKonvertierung.py", line 45, in <module>
    f.write('%g\n' % (Measurements[Kind][k]))

TypeError: must be real number, not str


Schon mal vielen Dank für die Hilfe!

Grüße Leon
OozeWithUzi
User
Beiträge: 9
Registriert: Montag 8. Juli 2019, 13:40

Puhhh da ist ne ganze Menge schief an deinem Code.

Aber zum Fehler: Du versuchst mit %g einen Floating Point Wert in die Datei zu schreiben und der Wert, den du aus dem Dict ziehst, ist ein String.
Mit %s sollte der Fehler dann nicht mehr kommen.

Ansonsten:
Warum erzeugst du mehrfach neue (sliced) Listen aus lines? Das Herauslesen der Daten sollte auch in einer for Schleife möglich sein.
Was ist das i? Da wäre ein beschreibenderer Name sinnvoller. Für x gilt dasselbe.
Wo ich gerade bei x bin, warum verwendest du das beim Schreiben in die Datei nicht wieder?
Du benutzt auch NumberOfMeasurements nicht und wenn wäre das number_of_measurements.

Code: Alles auswählen

n = len(lines)
    for line in lines[1:n-1]:
Besser:

Code: Alles auswählen

for line in lines[1:]:
Machst du oben ja auch...

Eine Datei kann man auch als Context Manager öffnen. Sollte man sogar: Lesbarkeit und Robustheit.
Du solltest dir mal List/Dict Comprehensions ansehen.
Strings werden nicht mit '+' zusammen gelötet. Dafür gibt es .format oder f string literale.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo leooonidas,

der Fehler ist, dass Du aus einer Datei nur Strings liest, diese aber versuchst als Zahl zu formatieren. Entweder schreibst Du also direkt den String oder wandelst ihn vorher in eine Zahl um.

Zum Code: Nach Konvention werden Variablennamen klein_mit_unterstrich geschrieben, also times_of_measurement.
Einbuchstabige Namen vermeiden, weil sie nicht aussagekräftig sind.

Dateien mit dem with-Statement öffnen und immer ein Encoding angeben.

Schleifen über einen Index sind schlecht, wenn man auch direkt über die Elemente der Liste iterieren könnte.

Zusammengehörige Daten zusammen verarbeiten und in einer Datenstruktur speichern. Du hast zwei Schleifen zum Lesen, eine für die Zeiten, eine für die Messwerte und speicherst diese auch in zwei bzw. viele Listen ab. Besser wäre es also, die Zahlen zusammen zu halten und statt des Wörterbuchs mit Listen, eine Liste mit Wörterbüchern zu führen.

`lines[1:n-1]` ignoriert nicht nur die erste Zeile sondern auch die letzte Zeile; willst Du das wirklich?

Wenn die Text-Datei schon einen Header hat, in dem die Spalten schön benannt sind, dann ignoriere ihn nicht, sondern nutze ihn.
Hilfreich wäre vielleicht dabei auch das csv-Modul, falls die Daten z.B. Tab-separiert wären.

NumberOfMeasurement wird gar nicht benutzt, und eigentlich auch gar nicht gebraucht.

Bei der Länge eines Programms sind bereits Funktionen notwendig, einfach um den Code besser zu strukturieren, statt das mit Kommentaren zu tun.

Das ganze könnte dann so aussehen:

Code: Alles auswählen

KINDS_OF_MEASUREMENTS = ["RC", "Dnear", "Dfar"]

def read_measurements(filename):
    measurements = []
    with open(filename, encoding='utf8') as lines:
        _header = next(lines) # TODO: use this header
        for line in lines:
            parts = line.split()
            measurements.append({
                "time": parts[1],
                "RC": parts[8],
                "Dnear": parts[9],
                "Dfar": parts[10],
            })

def write_measurements_of_kind(filename, kind, measurements):
    with open(filename, "w", encoding="utf8") as output:
        for measurement in measurements:
            output.write("%s\n" % measurement[kind])

def main():
    measurements = read_measurements("test.txt")
    for kind in KINDS_OF_MEASUREMENTS:
        write_measurements_of_kind(kind + ".txt", kind, measurements)

if __name__ == '__main__':
    main()
leooonidas
User
Beiträge: 2
Registriert: Montag 15. Juli 2019, 10:03

Hallo OozeWith Uzi und Sirius3,


vielen Dank für die schnellen, ausführlichen Antworten und die Tipps für die bessere Strukturierung in der Zukunft! Das hat schon sehr geholfen.

Das lines[1:n-1] iat tatsächlich absicht, da die Datei die ich auslesen teilweise eine Zeile mehr bzw. weniger hat und es sonst zum Fahler "out of range" kam.


Grüße Leon
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@leooonidas: dann solltest Du genau den Fehler abfangen, und nicht pauschal die letzte Zeile weglassen.
OozeWithUzi
User
Beiträge: 9
Registriert: Montag 8. Juli 2019, 13:40

Und dann kannst du auch lines[1:-2] schreiben. Dann sparst du dir das n.

Das löst aber nicht das Problem, dass du lieber den Fehler abfangen solltest, wie von Sirius3 beschrieben.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@OozeWithUzi: es bleibt bei lines[1:-1], sonst wären zwei Zeilen weg.
OozeWithUzi
User
Beiträge: 9
Registriert: Montag 8. Juli 2019, 13:40

@Sirius3: Argh. Ja, mein Fehler. Danke für die Korrektur.
Antworten