Seite 1 von 1

os.popen() bzw. commands.getoutput()

Verfasst: Sonntag 7. März 2004, 14:59
von hiroki
Hi!

Ich hab eine Frage bezüglich der beiden oben genannten Befehle.
Und zwar, ich muss mittels eines der beiden Befehle popen() bzw. getoutput() ein Programm ausführen. Dieses Programm jedoch läuft sehr lange (es ist ein programm zum encoden).
Ich möchte mit Python nun dieses Programm immer wieder ausführen für alle Dateien im Verzeichnis. Soweit kein Problem.

Mein Problem / Meine Frage setzt bei der Ausgabe dieses encoder-Programms an. Ich habe schon diverse Befehle ausprobiert.

Ich möchte, dass wenn der Encoder aufgerufen wird die Ausgabe des Programms auch auf dem Bildschirm erscheint, und zwar sofort! Im Moment gibt Python den Anfang der Ausgabe aus, und erst wenn das Programm terminiert wird die restliche Ausgabe auf den Bildschirm geschrieben. Ich weiß jedoch, dass das Programm ständig eine Fortschrittsanzeige aktualisiert, die wird jedoch erst angezeigt wenn das Programm sowieso beendet ist. Wie kann ich nun machen, dass der Fortschritt mir auch in python sofort ohne Pufferung o.ä. angezeigt wird?

Code: Alles auswählen

#!/usr/bin/env python

import glob, time, os, commands

if __name__ == "__main__":
        log = open("realcap.log", 'w')
        encoder = "mencoder -ovc lavc -lavcopts vcodec=mpeg4 -oac mp3lame -o %s %s"
        filelist = glob.glob("ITC2*.rm")
        urllist = []
        print "The following RealMedia files were found:"
        print " ".join(filelist), "\n"
        print time.ctime(), "\tStarted capturing of %d RealMedia files" % len(filelist)
        print >> log, time.ctime(), "\tStarted capturing of %d RealMedia files" % len(filelist)
        for file in filelist:
                f = open(file, 'r')
                url = f.readline()
                urllist += [url]
                f.close()
        print "".join(urllist)
        for url in urllist:
                url = url.replace("\r\n", "")
                filename = url.split("?")[0]
                filename = "cap_" + filename[filename.rfind("/")+1:] + ".avi"
                command = encoder % (filename, url)
                print "Fetching RealVideo Stream from:", url
                print time.ctime(), "\tCapturing", filename, "started"
                print >> log, time.ctime(), "\tCapturing", filename, "started"
                print os.popen(command).read()
                #for line in os.popen(command).readlines():
                #       print line,
                #print commands.getoutput(command)
                #print "".join(os.popen(command).readlines())
                print >> log, time.ctime(), "\tCapturing", filename, "finished"
                print time.ctime(), "\tCapturing", filename, "finished"

        print >> log, time.ctime(), "\tFinished capture process"
        print time.ctime(), "\tFinished capture process"
        log.close()
Das ist das Programm so wie es jetzt aussieht. Die Möglichkeiten wie ich versucht habe es auszugeben, damit die Ausgabe nicht verzögert erfolgt sind auskmmentiert, also folgende Zeilen aus obigem Programmtext:

Code: Alles auswählen

                print os.popen(command).read()
                #for line in os.popen(command).readlines():
                #       print line,
                #print commands.getoutput(command)
                #print "".join(os.popen(command).readlines())
Danke schonmal für Eure Hilfe,

hiroki

Verfasst: Sonntag 7. März 2004, 16:45
von hiroki
Ich hab ein einfaches Beispiel für mein Problem gefunden, also müsst Ihr Euch nicht oben durch den Quelltext "quälen" ;)

Code: Alles auswählen

print "".join(os.popen("ping google.de -c 5").readlines())
hier hätte ich also gerne, dass nach und nach (wie beim echten ping) jede Zeile ausgegeben wird. Was er jedoch in Wirklichkeit tut ist auf das Ende des Programmlaufs zu warten und dann alles auf einmal auszugeben.

Wie kann ich das verhindern? -> Also eine "Echtzeit"-Ansicht bekommen?

danke,

Hiroki

PS: Ach ja, ich weiß, dass es os.system() gibt, jedoch möchte ich auch die Ausgabe auswerten können :/ Dadurch entsteht das Problem ja überhaupt erst...

Verfasst: Sonntag 7. März 2004, 18:20
von Milan
Hi. Aus meinen Erfahrungen dazu ist es nicht möglich, die Ausgabe in Echtzeit abzupassen. Auf jeden Fall nicht mit commands.getoutput und ich glaube auch nicht mit Versionen von popen. Hier bin ich mir jedoch nicht sicher. Ich glaube, dazu mal was in der Docu gelesen zu haben, aber weiß es nicht mehr. Mit den Funtionen popen-popen4 denk ich mal nicht. Es ist aber unter Linux/Unix möglich mehr zu machen: Das Modul popen2 stell dieselben Funktionen bereit (Rückgabewerte in anderer Reihenfolge), aber es sind unter Linux auch noch die KLassen Popen3 und Popen4 verfügbar. Von denen kann man ableiten und damit eventuell was anstellen.

hth, Milan

Verfasst: Montag 29. März 2004, 16:06
von NEBULA
Ich hatte hier bei mir ein aehnliches Problem:

Ich habe unter Linux den mplayer im Slave-Modus gestartet und wollte natuerlich auch die Antworten lesen die bei einem get_percent_length kommen :) und das funktionierte auch am Anfang so irgendwie gar nicht.
Erst bei Beendigung des Programmes, konnte mein Popen3-Objekt vom stdout-Dateiobjekt lesen....

Mir ist eingefallen, dass die Jungs von Freevo wohl auch vor diesem Problem gestanden haben muessen und richtig.

Tip daher:

Freevo-Quellcode herunterladen und dort nach childapp.py suchen ;)
Ich bin hingegangen und habe versucht von Grund auf dieses Modul nachzubilden, es funktioniert aber leider......

So richtig durchgeblickt habe ich da ehrlich gesagt nicht, aber der Trick besteht wohl darin in einem eigenen Thread an den Ausgabestreams(stdout und stderr) zu lauschen.
Meine "mplayer Aufgabe" funktioniert nun auch so wie man sich das wuenscht.