Seite 1 von 1

Fortschrittsbalken in Python

Verfasst: Freitag 16. April 2010, 16:56
von snafu
Ich kenne das Projekt ProgressBar auf PyPi und habe auch einige Ideen davon übernommen. Trotzdem möchte ich den Code neu schreiben und einige Verbesserungen hinzufügen, da das Projekt ja irgendwie tot zu sein scheint. Bis alle Features implementiert sind, wird es noch ein Weilchen dauern, aber hier ein Vorgeschmack. Ich arbeite sehr viel mit Vererbung, weil ich glaube, dass das in dem Fall angebracht ist. Dokumentation habe ich bisher noch gar nicht geschrieben, wohl auch, weil ich den größten Teil erst heute Nachmittag zu Bildschirm gebracht habe. Hier mal ein Verwendungsbeispiel, wie gesagt: Pre-Alpha oder so ;P :

Code: Alles auswählen

In [1]: from progress import ProgressBar, FormattedPercentValue, write_string

In [2]: bar = ProgressBar(0,180, width=70)

In [3]: percentage = FormattedPercentValue(0,180)

In [4]: from time import sleep

In [5]: for i in xrange(1,181):
   ...:     bar.curval = percentage.curval = i
   ...:     s = '{0} {1}'.format(percentage, bar)
   ...:     write_string(s)
   ...:     sleep(.1)
   ...:     
   ...:     
100.0% [===================================================================>]

Verfasst: Freitag 16. April 2010, 18:01
von ms4py
Eine Klasse, die die beiden Elemente vereint, würde die Redundanz von deinem Code-Beispiel nehmen und deutlicher eleganter wirken.

Verfasst: Samstag 17. April 2010, 04:23
von snafu
Ja, ist mir bewusst. Eine Klasse RendererContainer ist in Arbeit. Bei dem nächsten Code, den ich zeigen werde, wird wahrscheinlich auch ein Dekorator @progress_string dabei sein, der von "seiner" Funktion (beispielhaft sei der Callback von urllib.urlretrieve genannt) nur noch den aktuellen Wert und den Endwert erwartet. Für diejenigen, die das weiterhin händisch machen möchten, werde ich zudem auf die __add__-Methode eines Renderers einen Alias für curval setzen. Und die __add__-Methode des Containers führt dann entsprechend die __add__-Methoden ihrer Renderer aus.

Um ehrlich zu sein, wollte ich erstmal eine Prozentzahl samt animierten Balken haben. Ich bin eher jemand, der lieber ein Ergebnis sieht und sich anschließend um die Feinheiten in der Struktur kümmert. Zuviel Nachdenken über theoretische Details verdirbt mir nämlich auf Dauer die Lust an einem Projekt. Wobei das Design IMHO sooo schlecht gar nicht ist. Es fehlt quasi noch etwas an den gewissen Shortcuts, die eine API wirklich komfortabel machen.

Verfasst: Mittwoch 28. April 2010, 08:58
von snafu
Ich hab nochmal etwas umgebaut:

Code: Alles auswählen

In [1]: from time import sleep

In [2]: from callisto import ProgressValue, write_string

In [3]: progress = ProgressValue()

In [4]: progress.end = 180

In [5]: progress.renderers['pbar'].width = 70

In [6]: for i in xrange(1, 181):
   ...:     progress.current = i
   ...:     write_string(progress.render('{percent} {pbar}'))
   ...:     sleep(.1)
   ...:     
   ...:     
100.0% [===================================================================>]
Den Code dazu gibt's hier. Die Verrenkung mit der Breite wird man später nicht mehr machen müssen, da ich Funktionalität einbauen werde, die automatisch erkennen soll, wieviel Platz noch für den Fortschrittsbalken übrig ist. Mit dem angekündigten Dekorator wird dann alles auch nochmal etwas schöner. Zusätzlich baue ich Hilfen zum Testen ein, so dass man bereits eine Ausgabe erhalten kann, wenn man nur xrange() übergibt. Übrigens hoffe ich, das mit den automatischen Zuweisungen der Formatier-Argumente ist nicht zu magisch geworden.

Verfasst: Sonntag 2. Mai 2010, 16:15
von snafu
Ich mal wieder. Das versprochene Feature, bei dem sich der Prozentbalken anpasst, ist enthalten. Zudem gibt es nun ".done()" für den ProgressValue, welches bei Bedarf von einem entsprechenden Renderer implementiert werden kann - mein Rotator macht das z.B.

Naja, vielleicht kommt ja in nächster Zeit noch Rückmeldung. Mir jedenfalls macht das Projekt Spaß. Achso, die API wurde auch nochmal ein bißchen verbessert. Ein simpler Test kann so ausgeführt werden:

Code: Alles auswählen

callisto.test('{percent} {pbar} {rotator}')
TODO u.a.:
- Rausfinden, wieso der Rotator plötzlich bei sehr kurzen Intervallen nicht mehr die Bremse zieht, so wie es eigentlich durch den Ticker bereitgestellt werden sollte und IMHO auch in vorherigen Versionen wurde.
- Implementieren von Zeit und Datenübertragungsraten mit einigermaßen intelligenter Nutzung der Maßeinheiten
- Hilfsfunktion, um die Ausgabe eines laufenden Prozesses verarbeiten zu können
usw...

http://paste.pocoo.org/show/208849/

Huch, Zeile 58 ist ein Übrigbleibsel, das da eigentlich nicht mehr stehen sollte. :lol:

Verfasst: Dienstag 4. Mai 2010, 15:30
von Twilo
Hallo,

gibt es etwas vergleichbares für Windows, was auch unter Linux funktioniert?

mfg
Twilo

EDIT: was haltet Ihr von python-progressbar?

Verfasst: Donnerstag 6. Mai 2010, 09:03
von snafu
Etwas für Windows, das auch unter Linux läuft, entspricht ja dem, was man landläufig als "plattformunabhängig" bezeichnen würde. Genau so etwas habe ich vor. Das von dir genannte Tool habe ich ja selbst im OP erwähnt und ich will meins als eine Art Nachfolger herausbringen. Es soll später im Großen und Ganzen die Funktionalität von `python-progressbar` unterstützen - nur eben anders strukturiert - sowie weitere Features.

Was übrigens die Abhängigkeit von Curses angeht, so könnte man sich unter Windows z.B. den Python 2.6 Port von `wcurses` installieren (http://www.lfd.uci.edu/~gohlke/pythonlibs/). Das mag nur zur Ermittlung der Terminalgröße noch etwas Overkill sein, aber ich will früher oder später auch "Inverse-Gimmicks" einbauen. Ein Beispiel wäre Schrift im Fortschrittsbalken, die im entsprechend durchlaufenen (weißen) Bereich die Gegenfarbe annimmt. Ich hoffe, `wcurses` hat das implementiert. Generell sollen wahrscheinlich auch Farben unterstützt werden.

Auch hatte ich ja schon das live-mäßige Auslesen von Prozess-Ausgaben erwähnt. Fernziel ist hier ein intelligenter Parser, der typische Fortschrittsangaben erkennt und in `ProgressValue`s umwandelt, so dass diese Angaben nicht nur isoliert, sondern auch in verändertem Design angezeigt werden können. Dazu würden dann natürlich auch GUI-Toolkits zählen, die den Prozess starten, Callisto die niederen Arbeiten erledigen lassen und nur noch die resultierenden Werte mit ihren grafischen Elementen verknüpfen. Dies ist aber wie gesagt noch Zukunftsmusik. Erstmal werden die häufig gebrauchten Prozess-Widgets zu Ende implementiert und dann auch mal released, sobald ich der Meinung bin, dass die API sich ausreichend gefestigt hat.

Verfasst: Donnerstag 6. Mai 2010, 17:16
von Twilo
Hallo,

gibt es wcurses auch für python2.5 oder mod_python für python2.6?
Immer diese Abhängigkeiten :?

mfg
Twilo

Verfasst: Donnerstag 6. Mai 2010, 18:53
von lunar
Was genau hat mod_python nun mit diesem Thema zu tun?!

Verfasst: Donnerstag 6. Mai 2010, 19:12
von ms4py
lunar hat geschrieben:Was genau hat mod_python nun mit diesem Thema zu tun?!
Außerdem sollte man sowieso WSGI verwenden...

Verfasst: Donnerstag 6. Mai 2010, 19:27
von Twilo
Hallo,
lunar hat geschrieben:Was genau hat mod_python nun mit diesem Thema zu tun?!
auf dem Rechner läuft ein Apache mit mod_python. Da es mod_python nicht für python2.6 gibt(?), wurde python2.5 installiert.

Auf dem gleichen Rechner wollte ich in der Konsole einen Fortschrittsbalken ausgeben.

mfg
Twilo

Verfasst: Donnerstag 6. Mai 2010, 20:07
von ms4py
Twilo hat geschrieben:auf dem Rechner läuft ein Apache mit mod_python. Da es mod_python nicht für python2.6 gibt(?), wurde python2.5 installiert.
Du kannst/solltest trotzdem WSGI verwenden. Zum Deploy kannst du immer noch mod_python verwenden.

Siehe dazu auch in der Python-Dokumentation "HOWTO Use Python in the web", hier ein Ausschnitt.
These are the reasons why mod_python should be avoided when writing new programs. In some circumstances it might be still a good idea to use mod_python for deployment, but WSGI makes it possible to run WSGI programs under mod_python as well.
Eine ausführliche, deutsche Einführung in WSGI findest du außerdem hier:
http://docs.google.com/fileview?id=0Bxc ... MzAw&hl=en

Verfasst: Donnerstag 6. Mai 2010, 20:23
von snafu
Bitte tut mir den Gefallen und lasst das jetzt nicht ausufern...

Re: Fortschrittsbalken in Python

Verfasst: Donnerstag 13. Mai 2010, 15:03
von snafu
Moin,

ich hatte mal wieder die Muße, ein bißchen was zu machen. Callisto unterstützt jetzt mehrzeilige Templates und erkennt bei Dateigrößen automatisch eine passende Einheit samt Umrechnung. Ob das genau so intelligent implementiert wurde, überlasse ich dem Leser... Hier dann mal ein erstes Beispiel, wie man es evtl später in-the-wild finden könnte:

Code: Alles auswählen

from contextlib import closing
from urllib import urlopen, urlretrieve
from callisto import ProgressValue

URL = 'http://python.org/ftp/python/2.6.5/Python-2.6.5.tar.bz2'

TEMPLATE = """
Downloading python 2.6.5 source-file... ({cursize} of {totsize})
{pbar} {percent}"""

def download_pysource(url=URL, template=TEMPLATE):
    with closing(urlopen(url)) as pysource:
        filesize = int(pysource.info()['Content-Length'])
    progress = ProgressValue(template=template, end=filesize)

    urlretrieve(url, reporthook=lambda blks,bsize,_: progress.render(blks*bsize))
    progress.done()
Das Ding funktioniert definitiv nur mit Unix - sorry dafür. Habe aber inzwischen Infos gefunden, wie man unter Windows mittels `ctypes.windll` die Terminalgröße rauskriegt und den Text einfärben kann. Das sieht im Großen und Ganzen alles etwas ordentlicher aus als das bekannte Beispiel mit `struct` und so (IMHO). Nach dem Ausprobieren von `wcurses` und etwas, das auf `PDCurses` aufbaut, bin ich doch etwas enttäuscht und werde mich halt selbst an die Sache machen. Wobei Windows-Support wohl eher zu den mittelfristigen Zielen gehören wird. Gibt vieles anderes, was mir momentan wichtiger erscheint.

Nochwas: Der "Progress" sollte grundsätzlich mit `.done()` abgeschlossen werden, damit die Klassen ein letztes Mal rendern und Abschlussarbeiten durchführen können. Ich hatte das ja schon vorher mal erwähnt. Wahrscheinlich werde ich den Nutzer letztlich mittels Contextmanager zu seinem Glück zwingen, aber das kommt ein ander Mal - wie auch die Doku. :)

Der Code: http://www.python-forum.de/pastebin.php?mode=view&s=9