nochmal threading

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
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

aufgrund eines anderen Threads hab ich mich an meinen ersten threading-Versuch erinnert, der nicht 100% richtig läuft.
Folgende Ausgangssituation:
Ich digitalisiere meine Vinyl-Sammlung und habe eine LP-Seite als .wav Datei vorliegen, diese splitte ich ich mit Hilfe des Kommandozeilen-Tools "sox".
Jetzt möchte ich wissen wie weit die Verarbeitung schon ist, mein Ansatz:

Code: Alles auswählen

def progress(path,total):
    changed = False
    len_old = len(os.listdir(path))
    while len_old < total:
        if changed:
            print u"\r progress: {0}%".format(l*100/total)
            counter = 0
        time.sleep(1)
        len_current = len(os.listdir(path))
        if len_old != len_current:
            changed = True
            len_old = len_current
        else:
            changed = False
            counter += 1
        if counter > 10:
            break
    return
        
def sox_split(project_path, orig_path, track_length, factor = 0):            
    prog = threading.Thread(target = progress, args=(project_path,track_length))
    prog.start()
    sox.split(project_path, orig_path, factor)
    print u"splitted!"   
    return

Beim ersten Aufruf klappt auch alles prima.
Falls beim splitten zu viel oder zu wenig Files entstehen, rufe ich die sox_split() noch einmal mit einem anderen "factor" auf. Dann funktionert die Ausgabe von progress() nicht richtig (wenn ich mich recht erinnere gibt progress() dann genau 1x "progress: 100%" aus und dann nichts mehr). Hab im Moment leider keine bessere Fehlerbeschreibung, da ich grad nicht am Digitalisieren bin und der letzte Fehler schon etwas her ist. Aber evtl. habt ihr zu dem Code an sich schon Ideen?
Auch wenn ich auf das Ende des Threads warte ändert sich nichts:

Code: Alles auswählen

def sox_split(project_path, mono_path, track_length, factor = 0):            
    prog = threading.Thread(target = progress, args=(project_path,track_length))
    prog.daemon = True
    prog.start()
    sox.split(project_path, mono_path, factor)
    while prog.is_alive():
        time.sleep(1)
    print u"splitted!"   
    return
Habt ihr noch eine Idee?
BlackJack

@mcdwerner: Der Quelltext ist nicht lauffähig weil `l` nirgends definiert wird. Übrigens ein schlechter Name, nicht nur weil er zu kurz und nichtssagend ist, sondern weil man bei vielen Schriftarten l und 1 nicht wirklich gut auseinander halten kann. Und ``1*x`` ist was anderes als ``l*x``. Das führt schnell zu Missverständnissen.

Wenn ich das richtig sehe gehst Du nach der Anzahl der Dateien in einem Verzeichnis. Wenn Du einmal gesplittet hast entstehen da ja welche. Die sind beim zweiten mal splitten dann schon da und es sieht nach dieser Art den Fortschritt zu bestimmen schon fertig aus.

Das Verfahren ist IMHO sowieso ziemlich fragil solange man nicht garantiert, dass in dem Verzeichnis niemand anders etwas macht und auch noch keine Dateien existieren die überschrieben werden.

Der Code in der ``while``-Schleife in `progress()` ist sehr ungünstig arrangiert. Eigentlich bräuchte man `changed`.

Auf das Ende eines `Thread`\s wartet man mit der `join()`-Methode.

Zeige den Quelltext 10 Programmieren und frage ob `prog` für `program` oder für `progress` steht. Ich würde es aussschreiben und nicht Abkürzen.
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@BlackJack:
- mit "l" und "prog" hast Du natürlich recht! "len_old" war bis kurz bevor ich's hier einstellte "l" ich dachte ich hätte alle geändert ;-)
(noch ein Nachteil von solch kurzen Bezeichnern: man kann sie nicht einfach suchen und ersetzen lassen, der Quelltext war auch eigentlich nicht zum Herzeigen gedacht)
-
Der Code in der ``while``-Schleife in `progress()` ist sehr ungünstig arrangiert. Eigentlich bräuchte man `changed`.
verstehe ich nicht! Wozu bräuchte man changed? Doch nicht als Bedingung für die while-Schleife, denn es könnte ja sein, dass ein Schreibvorgang länger als 1 Skunde dauert (das File wird beim Splitten von .wav in .ogg gewandelt!)
- die join-Methode werde ich mir ansehen
- das Verzeichnis in das ich schreibe wird von der aufrufenden Funktion neu erstellt und somit bin ich mir sicher, dass dort sonst nichts gemacht wird
- und dieses Verzeichnis sollte ich vor dem 2. Aufruf leer machen (mir fehlt hier immer wieder das face-palm-Smiley :roll: ) Das sollte dann auch mein beschriebenes "falsches" Verhalten erklären, thx again!
BlackJack

@mcdwerner: Facepalm fehlt wirklich — der Satz sollte eigentlich „Eigentlich bräuchte man `changed` nicht.” heissen. :oops: ← Den nehme ich in solchen Fällen immer. :-)

Jetzt wo ich mir den Code nochmal anschaue bin ich mir auch fast sicher, dass es ein Problem ist, dass `counter` vor der Schleife nicht initialisiert wird‽

Ungetestet mit Namen die besser aussagen was die Werte wirklich bedeuten:

Code: Alles auswählen

def watch_and_print_progress(path, expected_file_count, timeout=10):
    seconds = 0
    old_file_count = len(os.listdir(path))
    while old_file_count < expected_file_count:
        time.sleep(1)
        current_file_count = len(os.listdir(path))
        if old_file_count != current_file_count:
            print u'\r progress: {0}%'.format(current_file_count * 100 / expected_file_count)
            seconds = 0
        else:
            seconds += 1
            if seconds >= timeout:
                break
        old_file_count = current_file_count
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

Danke BlackJack! Dieses Forum macht meine Programmierkenntnisse doch immer wieder ein Stück besser :D
Antworten