Sortierung_ID3

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
geistlich
User
Beiträge: 2
Registriert: Montag 5. Dezember 2011, 12:25

Hallo zusammen,

nachdem ich mein erstes Pythonbuch durch habe, versuche ich mich nun an meinem ersten Projekt, "Sortierung_ID3". In einem bestimmten Ordner werden alle MP3-Dateien nach dem Album sortiert (und in den entsprechenden Unterordner kopiert, wenn es mehr als ein Album ist), und bekommen die Tracknummer an den Anfang des Dateinamens.
Dies erleichtert mir, meinen MP3-Bestand zu pflegen, wo ich bei diversen Alben nur die Dateinamen "Album - Titel" habe und so die Reihenfolge der Tracks bei der Wiedergabe falsch ist.

Grundlage meines Programms ist das Python Modul "id3reader" von Ned Batchelder (siehe hier), welches aus MP3-Dateien den ID3-Tag auslesen kann.

Hier der Code:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: cp1252 -*-

# Aufgaben des Programms:
# 1. Auslesen des Ausführungsordners
# und anschließende Umwandlung zum Unicodestring
# 2. Auslesen der Dateinahmen und Speicherung in eine Liste
# 3. Albumname ermitteln und prüfen, ob alle Tracks vom gleichen Album sind -
# ansonsten Unterordner mit Albumsname erstellen.
# 4. ID3-Tag "Track" des Dateinamens i auslesen und die Tracknummer in
# einem Dictionary speichern. Anschließend die Tracknummer an den Anfang des
# Dateinamens schreiben und Datei in den jeweiligen Albumsordner verschieben.

import os, id3reader, locale, sys

def main():
    if os.name == 'posix':
        os.system('clear')
    elif os.name == 'nt':
        os.system('cls')
    
    # 1. Auslesen des Ausführungsordners und anschließende Umwandlung zum Unicodestring
    # löschen # pfad = os.getcwd()
    
    if len(sys.argv) < 2:
        print 'Bitte einen Pfad angeben, der bearbeitet werden soll!'
        sys.exit()

    if sys.argv[1] == '.':
        pfad = os.getcwd()
    else:
        pfad = sys.argv[1]
        
    #print 'Der Pfad lautet: ' + pfad
    pfad = pfad.decode("iso-8859-15")
    
    # 2. Auslesen der Dateinahmen und Speicherung in eine Liste
    dateien = os.listdir(pfad)
    
    # Herauslöschen aller nicht MP3-Dateien aus der Liste
    for i in dateien[:]:
        if not i.endswith(".mp3"):
            index = dateien.index(i)
            del dateien[index]
    
    # 3. Albumname ermitteln und prüfen, ob alle Tracks vom gleichen Album sind -
    # ansonsten Unterordner mit Albumsname erstellen.
    dateien_album = {} # Directory mit IndexDateiname : Album
    dateien_album_Liste = []
    
    for i in range(0,len(dateien)):
        id3r = id3reader.Reader(dateien[i])
        dateien_album[i] = id3r.getValue('album')
        dateien_album_Liste.append(id3r.getValue('album'))
    
    if len(dateien_album_Liste) == 0:
        print "Es sind keine *.mp3-Dateien vorhanden!"
        exit()
    
    def sortiere(a, b):
        return locale.strcoll(a, b)
        
    dateien_album_Liste.sort(sortiere)
        
    anzAlben = 1
    indexAlben = {0:dateien_album_Liste[0]}
    for i in range(0, len(dateien)-1):
        dummyA = dateien_album_Liste[i]
        dummyB = dateien_album_Liste[i + 1]
        if dummyA <> dummyB:
            indexAlben[i+1] = dateien_album_Liste[i+1]
            anzAlben +=1
    print "Anzahl Alben: %d" %anzAlben
    #print "Folgende Ordner werden erstellt:"
    
    # Ordner für jedes ermittelte Album erstellen, wenn Anzahl Alben > 1
    if anzAlben > 1:
        for key in indexAlben:
            ordnerpfad = pfad + os.sep + indexAlben[key]
            if os.access(ordnerpfad, os.F_OK):
                print u"Der gewünschte Pfad \"%s\" ist bereits vorhanden!" \
                     %indexAlben[key]
            else:
                print "Der Ordner \"%s\" ist noch nicht vorhanden, er wird nun erstellt." \
                      %indexAlben[key]
                os.mkdir(ordnerpfad)
    
    # 4. ID3-Tag "Track" des Dateinamens i auslesen und die Tracknummer in
    # einem Dictionary speichern. Anschließend die Tracknummer an den Anfang des
    # Dateinamens schreiben und Datei in den jeweiligen Albumsordner verschieben.
    dateien_titel = {} # Directory mit IndexDateiname : Titel
    for i in range(0,len(dateien)):
        id3r = id3reader.Reader(dateien[i])
        dateien_titel[i] = id3r.getValue('track')
        pfad_alt = pfad + os.sep + dateien[i]
        if anzAlben > 1:
            pfad_neu = pfad + os.sep + dateien_album[i] + os.sep + \
                       dateien_titel[i] + " " + dateien[i]
        else:
            pfad_neu = pfad + os.sep + dateien_titel[i] + " " + dateien[i]
        #print "Typ pfad:", type(pfad), "Typ dateien[i]:", type(dateien[i])
        #print i, pfad_alt, "zu", pfad_neu
        os.renames( pfad_alt, pfad_neu)
        
    print "___________"
    print "Fertig!"

if __name__ == '__main__':
    main()
Was haltet ihr von dem Programm/ dem Programmcode? Ich verwende es parallel unter Windows und Linux.

Aktuell habe ich mit dem Programm noch ein Problem. Ich muss es in den Ordner mit den MP3-Dateien abspeichern (und die Datei "id3reader" natürlich auch). Als Parameter übergebe ich "." für den aktuellen Ordner. Gebe ich aber einen anderen Pfad an, kommt eine Fehlermeldung:
Traceback (most recent call last):
File "sortierung_id3.py", line 109, in <module>
main<>
File "sortierung_id3.py", line 52, in main
id3r = id3reader.Reader(dateien)
File "C:\Dokumente...\id3reader.py", line 212, in __init__
self.file = open(self.file, 'rb')
IOError: [Errno 2] No such file or directory: u'Weto - Ausgebrannt.mp3'


Woran kann das liegen? Verursacht das andere Modul das Problem?

Und in diesem Zuge noch eine Frage zum Pfad: Wie sollte ich diesen am Besten vom Benutzer abfragen? Ist meine Lösung so in Ordnung, dass der Pfad als Parameter übergeben werden muss, oder sollte ich lieber eine Inputbox machen, wo man den Pfad einhacken muss?

Danke schon einmal für eure Hilfe!

Gruß,
geistlich
deets

Da fallen gleich mehrere Dinge auf:

- das current working directory zu holen ist nicht noetig, der uebergebene Pfad wird eh relativ dazu aufgeloest
- dein Problem mit dem "alles ausser . geht nicht" liegt natuerlich daran, dass du den Pfad nicht mittels os.path.join zusammenfuegst, sondern nach dem os.listdir einfach nur den Namensbestandteil an id3reader uebergibst.
- man iteriert in Python ueblicherweise ueber die Werte von Listen, nicht ueber ein xrange & dann Zugriff via index.

Code: Alles auswählen

for name in dateien:
        id3r = id3reader.Reader(os.path.join(pfad, name))
Das herausloeschen von nicht-mp3-Dateien ist eher ungewoehnlich, und vor allem viel zu zeitaufwaendig (das boese Quadratmonster erhebt seinen schuppigen Schaedel). Mach lieber sowas

Code: Alles auswählen

dateien = [d for d in dateien if d.endswith("mp3")]
Last but not least dateien_Album_Liste ist ganz sicher die falsche Datenstruktur. Stattdessen ein Dictionary verwenden, welches den Dateinamen auf die ID3-Tags abbildet.
geistlich
User
Beiträge: 2
Registriert: Montag 5. Dezember 2011, 12:25

Hallo deets,

vielen Dank für dein Feedback! Ich werde sie mir später mal genauer zu gemüte ziehen und Änderungen vornehmen.
Das herausloeschen von nicht-mp3-Dateien ist eher ungewoehnlich, und vor allem viel zu zeitaufwaendig (das boese Quadratmonster erhebt seinen schuppigen Schaedel). Mach lieber sowas

Code: Alles auswählen

dateien = [d for d in dateien if d.endswith("mp3")]
Dann müsste dieser Code also nach dem Befüllen von "dateien" kommen, nicht? Er "löscht" dann alle nicht auf mp3 endenden Werte raus?

Gruß,
geistlich
deets

Na, du darfst das Dateien in der rechten Seite auch durch was anderes ersetzen. Aber da du ja keine Verwendung mehr fuer das original hast, kannst du es auch ueberschreiben.
Antworten