Zeilenumkehr Script

Code-Stücke können hier veröffentlicht werden.
Antworten
Argoth
User
Beiträge: 8
Registriert: Freitag 20. Februar 2009, 21:21

Hallo zusammen!
Ich habe 2 kleine Fragen bezüglich eines Scripts, das ich am schreiben bin. Erklärend muss ich anmerken, dass das mein erstes ist :oops:
Ich hab mich dazu schon mal durch die einschlägige Anfängerliteratur gewühlt (Byte of pthon etc) aber ich komm trotzdem irgendwie nicht drauf.

Es geht um folgendes: Ab und zu hat man (als Chemiker) Dateien mit Messdaten, deren Zeilenreihenfolge genau umgekehrt sein müsste, damit sie von der Auswertungssoftware gelesen werden kann, sprich Zeile 1 müsste eigentlich die letzte Zeile sein. Und genau das würde ich ganz gerne ein kleines Script erledigen lassen.

Dazu hab ich eine Testdatei "messdaten.dat" mit dem Inhalt

Code: Alles auswählen

#x-value y-value
1 2
3 4
5 6
angelegt.

Meine Idee war jetzt folgende: Ich lese jede Zeile der Datei aus, speichere jede Zeile als Element in einer Liste und nutze einfach liste.reverse() um die Reihenfolge umzudrehen. Dann speichere ich diese Liste in einer neuen Datei. Der Code dazu sieht wie folgt aus:

Code: Alles auswählen

# -*- coding: utf-8 -*-
#/usr/bin/python
'''This program aims to reverse the line order in a given file. This is useful for example for experimental data that is recorded backwards and therefore can't be read by certain software.

'''

import sys

if sys.version_info[0] != 3: 
	sys.exit('Need Python 3.0 or higher to run this program. Will quit now.')

inputfile = input('Please name the file you want to inverse: ')
f = open(inputfile)
linelist = []

def inverse():
	for line in f:
		linelist.append(line)
		linelist.reverse()
		
	newfile = open('inv_' + inputfile, 'w')
	newfile.write(linelist)
	newfile.close()
	
while True:
	line = f.readline()
	if len(line) == 0:
		break
	inverse()
	print(linelist)
f.close()
Dabei finden sich jetzt aber zwei dicke Stolpersteine. Erstens bekomm ich nen

Code: Alles auswählen

UnsupportedOperation: BufferedReader.write() not supported
Fehler beim ausführen. Wenn ich Zeile 21-23 auskommentiere und mir die Liste über den print Befehl anzeigen lasse stellt sich zudem heraus, dass die Reihenfolge nicht ganz passt:

Code: Alles auswählen

Output:
['5 6 \n', '1 2\n', '3 4\n']
statt

Code: Alles auswählen

['5 6 \n', '3 4\n', '1 2\n']
Könnte einer von Euch mir nen kleinen Tip geben, wo der Fehler liegt? Ich erwarte da auch überhaupt kein fertig gebackenes Scriptsondern nur nen Fingerzeig, aber irgendwie steh ich grad auf dem Schlauch...

Vielen Dank!
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Guck Dir mal das Beispiel an. Ist ohne diversen try-except Firlefranz. Sollte helfen.

Code: Alles auswählen

fi=open("inp.txt")
inhalt=fi.readlines()
inhalt.reverse()
fi.close()

fo=open("out.txt",'w')
for i in inhalt:fo.write(i)
fo.close()
Argoth
User
Beiträge: 8
Registriert: Freitag 20. Februar 2009, 21:21

Vielen Dank!
Hat wunderbar funktioniert! Ich seh schon, ich bin das viel zu umständlich angegangen, so ist es doch deutlich schlanker :)
Jetzt muss ich eigentlich nur noch error handling einbauen und mir überlegen, wie ich das skript dazu bringe die rautierte Zeile unangetastet zu lassen. Aber das wird schon, nochmal danke!
BlackJack

Fals der Kommentar immer in der ersten Zeile zu finden ist:

Code: Alles auswählen

def main():
    filename = 'test.txt'
    with open(filename) as in_file:
        with open('inv_' + filename, 'w') as out_file:
            lines = iter(in_file)
            out_file.write(lines.next())
            out_file.writelines(reversed(list(lines)))
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mit ``contextlib.nested`` könnte man eine Einrückungstiefe sparen, weil man die zwei ``with``-Statements zusammenlegen kann.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Hab ich probiert, aber das sah IMHO hässlicher aus, weil die ``with``-Zeile dann nicht mehr auf eine Zeile gepasst hat und ich einen '\' verwenden musste.

Und mit drei Ebenen kann ich ganz gut leben. :-)
Argoth
User
Beiträge: 8
Registriert: Freitag 20. Februar 2009, 21:21

Erst mal ein herzliches Dankeschön für die weiteren Anregungen! Wie ich sehe geht es immer schöner und schlanker :)
Ich hab das jetzt mal übernommen, aber da schein noch eine Unstimmigkeit zu sein, denn das attribut .next() ist in dem Kontext angeblich nicht korrekt.

Code: Alles auswählen

# -*- coding: utf-8 -*-
#/usr/bin/python
'''Kommentar ist erstmal irrelevant ;)

'''

import sys

if sys.version_info[0] != 3: 
	sys.exit('Need Python 3.0 or higher to run this program. Will quit now.')

def main():
    inputfile = input('Please name the file you want to inverse: ')
    with open(inputfile) as in_file:
        with open('inv_' + inputfile, 'w') as out_file:
            lines = iter(in_file)
            out_file.write(lines.next())
            out_file.writelines(reversed(list(lines)))
main()

Code: Alles auswählen

Output: python3 reverse_v2.py
Please name the file you want to inverse: messdaten.dat
Traceback (most recent call last):                     
  File "reverse_v2.py", line 19, in <module>           
    main()                                             
  File "reverse_v2.py", line 17, in main               
    out_file.write(lines.next())
AttributeError: 'TextIOWrapper' object has no attribute 'next'
Ist das eventuell Python3 spezifisch oder bin ich einfach nur unfähig? Ich mein das ist sehr gut möglich, schließlich beschränkt sich meine Programmiererfahrung auf ein bisschen rumspielen mit VB vor zig Jahren und wenigen Tagen Python.

Edit: Danke@Hyperion, ich vergess manchmal, dass nicht jeder nen 22" hat...
Zuletzt geändert von Argoth am Samstag 21. Februar 2009, 16:39, insgesamt 3-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich würd den Kommentar in Zeile 3 mal umbrechen ... das passt so nicht gut ins Forum rein hier ;-)
BlackJack

@Argoth: `next()` ist in Python 3 zu einer Funktion geworden. Also ``next(lines)`` anstelle von ``lines.next()``.
Argoth
User
Beiträge: 8
Registriert: Freitag 20. Februar 2009, 21:21

Danke, wieder was gelernt! Die community hier ist echt bemerkenswert, Danke :)

Das Problem hat sich damit erledigt, ich werd das Skript warscheinlich noch etwas ausbauen, aber das will ich definitiv selber hinbekommen :)

Danke an alle für die konstruktiven Anregungen.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Genauer: <obj>.next ist zu <obj>.__next__ geworden, und man nutz die Funktion next um es aufzurufen, wie bei len und <obj>.__len__.
Antworten