Formatierung in einer TXT Datei.

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
frannek
User
Beiträge: 33
Registriert: Dienstag 28. Januar 2014, 12:17

Hallo zusammen. Ich habe eine Frage bezüglich einer formatierten Ausgabe in einer TXT Datei. Ich komme hier leider nicht weiter und hoffe auf eine kleine Unterstützung.
Derzeit habe ich es so, dass die Ausgabe des "Namens" in einer Zeile getrennt mit Tabulatoren erfolgt. In der darauf folgenden Zeile werden die Werte eingetragen..ebenfalls mit Tab getrennt.
Nun muss ich leider diese Art des loggings wieder umstricken und dabei komme ich ins straucheln.
Es soll also nicht mehr alles auf zwei Zeilen beschränkt werden sondern die Namen in der ersten Spalte und der Wert mit Tabulator daneben.

Beispiel ist:
Name1 Name2 Name3
512 544 132

Beispiel Soll:

Name1 512
Name2 544
Name3 132

Der Code zum "ist" schaut so aus:

Code: Alles auswählen

        for sn in sensornames:
            myfile.write('\t{sn}'.format(sn=sn))

        for sn in sensornames:
            myfile.write('\t{sn}t'.format(sn=sn))  

        myfile.write('\r\n\n{d} {t}'.format(d=heute.strftime('%d-%b-%Y'), t=Zeit2))
	
	count = 1
        for sv in pressure_list:
            myfile.write('\t{val}'.format(val=pressure_list[count]))
	    count += 1

	count = 1
        for sv in temp_list:
            myfile.write('\t{val}'.format(val=temp_list[count]))
	    count += 1


Wie könnte ich dies am einfachsten anstellen? Mir fehlt hierzu ein Beispiel bzw. die Idee, wie man das anstellen könnte.


Gruß
frannek
BlackJack

@frannek: Du müsstest halt statt alle Listen nacheinander abzuarbeiten und dann jeweils die Werte einer Zeile als auszugeben eine Schleife über die zusammengehörien Elemente aus allen Listen machen und die dann jeweils schreiben. An der Stelle könnte man auch mal fragen warum die Werte die zusammengehören überhaupt in solchen ”parallelen” Datenstrukturen stecken und nicht gleich zusammen, zum Beispiel als Tupel zusammengefasst, in *einer* Liste stecken.

Um die verschiedenen Listenelemente zusammenzuführen gibt es die `zip()`-Funktion. (In Python 2 eventuell auch `itertools.izip()`). Dieses iterieren über eine Zählvariable die als Index in die Liste(n) verwendet wird sollte man in Python nicht machen. Das Du das bei *einzelnen* Listen machst und dann auch noch über die Elemente iterierst, damit dann aber gar nichts machst und parallel noch eine Indexvariable manuell hochzählst ist total schräg. Was glaubst Du denn was `sv` in diesen beiden Schleifen ist?

Zum schreiben einer solchen Datei würde ich auch das `csv`-Modul verwenden und da nicht selber etwas basteln.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Die schnelle Antwort lautet: ``zip()``

Du kannst ja sicherlich beide Zeilen für sich gesehen in eine Liste parsen, dann hast Du in etwa folgendes:

Code: Alles auswählen

names = ["foo", "bar"]
values = [42, 99]
Diese getrennten Strukturen kannst Du paarweise mit ``zip`` zusammenfügen und dann weiterverarbeiten:

Code: Alles auswählen

list(zip(names, values))
> [('foo', 42), ('bar', 99)]

for name, value in zip(names, values):
    print(name, value)
>
foo 42
bar 99
Ganz einfach eigentlich :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ungetestet:

Code: Alles auswählen

with open('ist.txt') as infile:
    with open('soll.txt', 'w') as outfile:
        for line in zip(*map(str.split, infile)):
            print(*line, sep='\t', file=outfile)
frannek
User
Beiträge: 33
Registriert: Dienstag 28. Januar 2014, 12:17

Hallo Zusammen. Die Zip-Geschichte gefällt mir ganz gut :-) Ich hatte derweil noch bissle rumprobiert und hab dann soetwas gestrick:

Code: Alles auswählen

count = 1
for sn in sensornames:
    myfile.write('{sn}\t{i}\t{pv}\t{d}\t{t}\r\n'.format(sn=sn, i=count, pv=pressure_list[count], d=heute.strftime('%d.%m.%Y'), t=datetime.datetime.now().strftime("%H:%M:%S")))
    count += 1
Was ist davon zu halten? Nach dem Motto "geht, aber nicht schön" oder ist dies eher unzuverlässig?
Zuletzt geändert von Hyperion am Donnerstag 19. März 2015, 15:19, insgesamt 2-mal geändert.
Grund: Code in Python Code Tags gesetzt und Einrückungen korrigiert!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nicht schön würde ich in "unpythonisch" wandeln und das führt imho automatisch zu nicht wartbar und das wiederum zu "unzuverlässig" ;-)

Das pythonische Vorgehen ist es, hier die separaten Strukturen mittels ``zip`` zusammenzufassen. Dann braucht man auch keinen händischen Zähler!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@frannek: Statt später zusammenführen wäre wie gesagt gleich passen strukturieren die bessere Lösung.

Die Formatangaben für Objekte aus `datetime` kann man auch direkt in den Platzhaltern bei der Zeichenkettenformatierung unterbringen. Und `heute` + das ermitteln der aktuellen Zeit in getrennten Spalten halte ich für einen Programmfehler weil da Murks bei heraus kommen kann, nämlich das Datum von `heute` aber schon Uhrzeiten vom nächsten Tag. Ich würde vor der Schleife `now()` ermitteln und diesen Wert dann sowohl für Datum als auch für Zeit in die Ausgabedaten schreiben. Und ich würde da sehr wahrscheinlich auch nur *eine* Spalte draus machen, denn letztendlich ist das ja auch nur *ein* Wert.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@frannek: und dann natürlich noch enumerate statt händisch einen Zähler zu zählen und das verwenden des csv-Moduls.
Antworten