wx.ProgressDialog für pickle.load

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Azrael
User
Beiträge: 5
Registriert: Donnerstag 31. März 2005, 13:57

Montag 22. August 2005, 10:51

Hi!

Ich habe hier gerade ein Problem an dem ich nicht weiterkomme, wäre schön wenn jemand ne Lösung wüßte:

Ich schreibe ein Programm mit wxPython, in dem ich Dateien lese und schreibe über pickle. Dafür hätte ich gerne Ladebalken. Prinzipiell ja auch kein Problem mit wxGauge und/oder wx.ProgressDialog. Leider bekomme ich von pickle nicht zurück, wieviel er bereits geladen oder gespeichert hat -sprich, ich kann für den Balken kein Maximum angeben und auch keine sinnvollen Zwischenwerte. Normalerweise würde ich an dieser Stelle so einen Fortschrittsbalken nehmen, der einfach nur hin und herwandert (so ähnlich wie ein Throbber). Das heißt in Java "indeterminate" und läßt sich als Paramter angeben.
Für wxPython gibt es das wohl auch laut google, aber nur für Mac.
Aber für Windows finde ich da gar nichts? Hat jemand ne Lösung, entweder für so einen "unbestimmten" Fortschrittsbalken, oder wie man von pickle sinnvolle Fortschrittswerte bekommt?
Bin dankbar für jede Hilfe! :-)

Gruß,
Martin
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 22. August 2005, 11:08

Du könntest nicht direkt die Datei mit pickle laden, sondern erstmal Blockweise in einen String packen. Dabei kannst du einen Fortschrittsbalken laufen lassen. Nach dem die Datei geladen ist, kannst du es mit pickle umwandeln...

Aber wie groß sind deine Pickle Daten, das es so lange dauert, diese zu laden?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Gast

Montag 22. August 2005, 11:55

Nette Idee mit dem Umwandeln - vielleicht probiere ich das mal.
Riesig sind die Daten nicht, aber es fällt schon etwas an ;-)
Meine "Testdatei" hat 1,5MB, aber ich denke das wird bei ernsthafter Benutzung eher mehr. Also Größenordnung von einigen MB. Da braucht pickle dann ein paar Sekunden. Nicht wirklich lange, aber lange genug, daß ich gerne einen Fortschrittsbalken hätte ;-)

Gruß,
Martin
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 22. August 2005, 12:20

Naja, dann ist das eigentliche laden der roh Daten aus der Datei ja in Burchteilen von Sek. fertig...
Du könntest natürlich auch noch faken... Das laden der Daten geht von 0-90% und das umwandeln, dann die restlichen Prozente...

Oder du speicherst einfach die Zeit, die ein laden + umwandel früher gedauert hat und machst einen spekulativen Fortschrittsbalken, beim nächsten mal... Aber ich weiß nicht ob sich der Aufwand lohnt ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Azrael
User
Beiträge: 5
Registriert: Donnerstag 31. März 2005, 13:57

Dienstag 23. August 2005, 10:13

*g* Könnte ich natürlich machen, ist aber auch nicht sooo toll ;-) Egal, dann muß es halt ohne Fortschrittsbalken gehen ;-)
BlackJack

Dienstag 23. August 2005, 22:30

Habe mal versucht eine "file-like" Klasse dazwischen zu schalten. Das funktioniert soweit auch, aber es wird durch das ständige ausgeben des Fortschritts wesentlich langsamer.

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import division
import os

class ReadFileWithCallback:
    def __init__(self, fileobj, size, callback=lambda a, b: None):
        self.fileobj = fileobj
        self.size = size
        self.callback = callback
        self.close = fileobj.close
        self.read_bytes = 0

    @classmethod
    def open(cls, filename, mode='r', callback=lambda a, b: None):
        return cls(open(filename, mode), os.path.getsize(filename), callback)
    
    def read(self, size=-1):
        result = self.fileobj.read(size)
        self.read_bytes += len(result)
        return result
    
    def readline(self, size=-1):
        result = self.fileobj.readline(size)
        self.read_bytes += len(result)
        self.callback(self.read_bytes, self.size)
        return result


def print_progress(current_bytes, max_bytes):
       print '%6.2f%% (%d of %d kB)\r' % (current_bytes / (max_bytes / 100),
                                          current_bytes // 1024,
                                          max_bytes // 1024),


class PlaylistEntry:
        pass


def test():
    import pickle
    cache_file = ReadFileWithCallback.open('.mkplaylist.cache',
                                           'rb',
                                           print_progress)
    print 'start'
    dummy = pickle.load(cache_file)
    print '\nstop'
    cache_file.close()


if __name__ == '__main__':
    test()
Die "Dummy" Klasse `PlaylistEntry` ist nur da um meine Testdaten laden zu können.
Antworten