Python 2 bestimmte Zeilen lesen?

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.
MrRatlos
User
Beiträge: 5
Registriert: Mittwoch 17. Dezember 2014, 07:48

Ich möchte aus einem Textdokument bestimmte Zeilen auslesen. Dabei kann ich die Buchstaben aber nicht Zählen, da die Länge der Zeilen variiert. :K
Mfg
MrRatlos
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Willkommen im Forum!

Wie bestimmst du denn die relevanten Zeilen? Und wo genau ist das Problem?

Momentan kann man dir nur sagen, dass das definitiv vielleicht moeglich ist.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@MrRatlos: Zeilen werden normalerweise auch durch Zeile-Ende-Zeichen gekennzeichnet, da ist es also egal, ob sie unterschiedlich lang sind. Dateien werden in Python sogar automatisch Zeilenweise gelesen, wenn Du über ein File-Objekt iterierst. Du mußt nur noch das Kriterium finden, das bestimmte Zeilen von nicht-bestimmten unterscheidet.
MrRatlos
User
Beiträge: 5
Registriert: Mittwoch 17. Dezember 2014, 07:48

Ja ich habe eine Musikliste habe, von der ich nur die Titel.mp3, nicht die anderen Informationen lesen möchte(wie Album, Genre,etc.). Dadurch variiert auch der Zeilenabstand zwischen den Titeln. :?:
Zuletzt geändert von MrRatlos am Mittwoch 17. Dezember 2014, 08:43, insgesamt 1-mal geändert.
MrRatlos
User
Beiträge: 5
Registriert: Mittwoch 17. Dezember 2014, 07:48

Das sieht so aus:
info_end
song_begin: Feuer.mp3
Time: 208
Title: Feuer
Genre: 152
mtime: 1402337320
song_end
song_begin: Himmelskind.mp3
Time: 213
Title: Himmelskind
Genre: 152
mtime: 1402337330
song_end
song_begin: Liebe.mp3
Time: 259
Title: Liebe
Genre: 152
mtime: 1402337342
song_end
song_begin: Mmmh.mp3
Time: 300
Title: Mmmh
Genre: 152
mtime: 1402337350
song_end
song_begin: Revulotion.mp3
Time: 266
Title: Revulotion
Genre: 152
mtime: 1402337370
song_end
song_begin: Seemann.mp3
Time: 175
Title: Seemann
Genre: 152
mtime: 1402337406
song_end
song_begin: As I Lay Dying - 94 hours.mp3
Time: 190
Artist: As I Lay Dying
AlbumArtist: As I Lay Dying
Title: 94 Hours
Album: Frail Words Collapse
Track: 1
Date: 2003
Genre: Other
Composer: As I Lay Dying
Disc: 1/1
mtime: 1407013112
song_end
song_begin: Forever.mp3
Time: 282
Artist: As I Lay Dying
AlbumArtist: As I Lay Dying
Title: Forever
Album: Frail Words Collapse
Track: 5
Date: 2006
Genre: Other
Composer: T. Lambesis
Disc: 1/1
mtime: 1407013112
song_end
song_begin: Dreamland.mp3
Time: 342
Artist: Hammerfall
AlbumArtist: Hammerfall
Title: Dreamland
Album: Legacy of Kings
Track: 4
Date: 1998
Genre: Rock
Composer: Jesper Strömblad/Joacim Cans/Oscar Dronjak
Disc: 1/1
mtime: 1405777370
song_end
song_begin: Starchild.mp3
Time: 475
Artist: Wintersun
AlbumArtist: Wintersun
Title: Starchild
Album: Wintersun
Track: 6
Date: 2004
Genre: Metal
Composer: Jari Mäenpää
Disc: 1/1
mtime: 1404309276
song_end
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@MrRatlos: wie schon geschrieben, die Zeilenlänge ist kein Problem, um das Du Dich kümmern müßtest. Was hast Du also schon ausprobiert? Welcher Code macht welche Probleme, die Du auf die Zeilenlänge zurückzuführen glaubst?
MrRatlos
User
Beiträge: 5
Registriert: Mittwoch 17. Dezember 2014, 07:48

Code: Alles auswählen

M = open("/var/lib/mpd/tag_cache").read()
print M[5:100]
So hab ich es schon mal versucht. Aber es sind ja nur die einzelnen Buchstaben, die er ausgibt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Arbeite doch erstmal das Tutorial durch. Dir fehlt einfach das Grundlagenwissen. Wenn du das drauf hast, dann bekommst du dein Problem sicher gelöst.
Das Leben ist wie ein Tennisball.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@MrRatlos
Mal zwei Dinge, mit denen Du schon mal experimentieren kannst:
  1. Über ein fileobject kann man iterieren:

    Code: Alles auswählen

    >>> any_file = open('test')
    >>> for line in any_file:
    ...     print line,
    ... 
    zeile 1
    zeile 2 zeile 2
    zeile 3 zeile 3 zeile 3
    
  2. Es gibt verschiedene string methods, die einem so manche Arbeit abnehmen:

    Code: Alles auswählen

    >>> 'this is a string ending with xxxx.mp3'.endswith('mp3')
    True
mutetella

P.S. Das von EyDu verlinkte Tutorial gibt es auch in deutsch.
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Als erster Ansatz:

Code: Alles auswählen

with open(dateipfad) as lines:
    for line in lines:
        if line.startswith('song_begin:'):
            song_title = line.lstrip('song_begin: ').rstrip('\n')
            print(song_title)
Jetzt muss man nur noch verstehen, was da passiert. ;)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@snafu: vorsicht, lstrip macht nicht das, was Du denkst!

Code: Alles auswählen

>>> line='song_begin: going_nowhere.mp3'
>>> line.lstrip('song_begin: ')
'where.mp3'
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Wenn die Daten verlässlich sind, wäre eine Möglichkeit:

Code: Alles auswählen

>>> 'song_begin: going_nowhere.mp3'[12:].rstrip('\n')
'going_nowhere.mp3'
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Auf verlässliche Daten sollte man sich IMHO nicht verlassen. :-) Zumal: Was heisst verlässlich? Man muss ja sowieso prüfen um die Zeilen heraus zu finden die mit diesem Präfix anfangen. Also wird das wohl eher so aussehen:

Code: Alles auswählen

if line.startswith(SONG_FILENAME_PREFIX):
    filename = line[len(SONG_FILENAME_PREFIX):].rstrip()
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack
Hmm... ich kann jetzt ehrlich gesagt keinen Unterschied erkennen... außer dass mein Beispiel hardcoded ist. Zumal der immer wiederkehrende Aufruf von ``len()`` doch kaum nötig sein dürfte. Darum meinte ich ja "... verlässlich ...". Wenn man sich nicht darauf verlassen kann, dass die Zeile, die den Filename enthält, mit 'song_begin: ' beginnt, dann funktioniert ja der ganze Ansatz nicht...

Oder?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Ich bei bei „die Daten” von den Zeilen ausgegangen, nicht nur von denen die den Dateinamen enthalten. Und das hardcoden einer magischen Zahl ist IMHO *deutlich* schlimmer als ein `len()`-Aufruf pro Dateiname. *Falls* das zu langsam ist, kann man es ja immer noch ändern — in eine Konstante — aber es ist halt robust was Änderungen angeht und man kann sich nicht verzählen.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Wenn man nach Clean Code programmieren will, ist BJ Lösung stets zu bevorzugen, robust und selbsterklärend.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:Und das hardcoden einer magischen Zahl ist IMHO *deutlich* schlimmer...
Nochmals: Mit meinem Konsolenbeispiel wollte ich MrRatlos lediglich eine Möglichkeit aufzeigen, wie er an den filename kommt. Natürlich würde das *so* nicht in den Programmcode gehören...

Wie auch immer, ich würde der ``startswith`` Lösung eine mit ``endswith`` vorziehen:

Code: Alles auswählen

def endswith_(text, endings):
    for ending in endings:
        if text.endswith(ending):
            return True
    return False

def get_filename(text, extensions):
    if endswith_(text, extensions):
        return text.split(':')[-1].strip()

Code: Alles auswählen

>>> line = 'song_begin: As I Lay Dying - 94 hours.mp3'
>>> get_filename(line, ('ogg', 'flac', 'mp3', 'wmv'))
'As I Lay Dying - 94 hours.mp3'
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Das ist doch dann gar nicht mehr eindeutig und würde auch Sachen erwischen die gar keine Dateinamen sind oder zumindest nicht in der Zeile stehen die hier gewünscht ist, nämlich die, die mit 'song begin: ' anfangen. Auf der anderen Seite werden eventuell Dateinamen nicht gefunden wenn sie andere Endungen haben als in der Liste stehen. Das schliesst sogar andere Schreibweisen mit ein von Endungen die in der Liste stehen wie 'Wav' oder 'MP3'. Es gibt aber noch 'mod', 'it', 'mid', 'midi', 'rmi', 'xm', 'ape', 'wma', 'mp4', 'mpa', 'aac', und was weiss ich noch für Endungen für Audiodateien.

Ausserdem sollte man auch den Punkt prüfen denn sonst werden auch Felder als Dateinamen ausgelesen die gar keine sind, wie zum Beispiel ein Kommentar 'Ad jingle of Aflac'.

`endswith_()` ist überflüssig — `str.endswith()` kann das bereits.

Das Aufteilen an Doppelpunkten wird falsche Ergebnisse liefern wenn mindestens ein Doppelpunkt im Dateinamen enthalten ist.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:... zumindest nicht in der Zeile stehen die hier gewünscht ist, nämlich die, die mit 'song begin: ' anfangen.
Eben. Da sind wir wieder bei den "verlässlichen" Daten. Ich denke, beim Dateiname einer Audiodatei kann man sich eher darauf verlassen, dass dieser eine "Audioextension" hat als darauf, dass die Zeile mit 'song_begin:' beginnt.
BlackJack hat geschrieben:Auf der anderen Seite werden eventuell Dateinamen nicht gefunden wenn sie andere Endungen haben als in der Liste stehen.
Stimmt. Die Liste ist letztlich entscheidend.
BlackJack hat geschrieben:Ausserdem sollte man auch den Punkt prüfen denn sonst werden auch Felder als Dateinamen ausgelesen die gar keine sind, ...
Ok, noch ein Punkt für Dich!
BlackJack hat geschrieben:`endswith_()` ist überflüssig — `str.endswith()` kann das bereits.
Och Menno, dass Python immer alles können muss...
BlackJack hat geschrieben:Das Aufteilen an Doppelpunkten wird falsche Ergebnisse liefern wenn mindestens ein Doppelpunkt im Dateinamen enthalten ist.
Gut, Du hast gewonnen! ``startswith`` ist wohl tatsächlich sinnvoller... :(

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Also ich hatte das so verstanden das das ein vorgegebenes Dateiformat ist und das eben genau die Zeilen gewünscht sind, die mit 'song_begin: ' anfangen. Das sieht nach dem Playlistenformat vom mpd (music player daemon) aus.
Antworten