Hi. Ich wollte dir irgendwann mal antworten, hatte aber keine Zeit. Jetzt fällts mir wieder ein
Die Methoden retrlines und retrbinary einer ftplib.FTP Instanz erlauben, dass du eine Callbackfunktion angibst, an die die Werte übergeben werden. Normalerweiese ist das die write Methode einer geöffneten Datei (Bsp:
ftp.retrlines("RETR xyz.txt",open("xyz.txt","r").write)), das muss aber nicht sein. Du kannst dir hier auch eine eigene Funktion (Klasse wäre vielleicht besser, da die Funktion mehrmals aufgerufen wird) basteln, mit der du zwar auch in eine Datei schreibst, gleichzeitig aber mitzählst, wieviele Bytes übertragen worden sind. Wenn man weiß wie groß die Datei auf dem FTP-Server war (size Kommando), kann man hieraus den Fortschritt errechnen.
Bei http wird das schon schwerer: der Server kann eine Dateigröße vor dem Download ansagen, muss es aber nicht. Auch implementiert Python hier keine so schöne Schnittstelle, so dass ich nicht wüsste, wie man hier vorgehen sollte. Da musst du dir die httplib vielleicht mal bis auf's Detail anschauen und eventuell eine eigene Klasse für Response-Objets schreiben, denn du kannst zwar die Header auslesen, aber den Dateiinhalt nur "mit einem Ruck" abrufen. Da musst du eine gepufferte Variante für finden, dann geht das auch.
So, nun vielleicht noch ein kleines Beispiel für die FTP-Variante:
Code: Alles auswählen
class downloadstate:
def __init__(self,filename,mode,filesize):
self.datei=file(filename,mode)
self.filesize=filesize
self.retrsize=0
if 'b' not in mode:
self.sep="\n"
else:
self.sep=""
def write(self,text):
text+=self.sep
self.datei.write(text)
self.retrsize+=len(text)
self.aktualisiere()
def aktualisiere(self):
pass
def close(self):
self.datei.close()
def __del__(self):
if not self.datei.closed:
self.datei.close()
import ftplib
dateiname="xyz.txt"
ftp=ftplib.FTP(...)
f=downloadstate(dateiname,"w",ftp.size(dateiname))
ftp.retrlines("RETR %s"%dateiname,f.write)
f.close()
ftp.quit()
Hier kannst du nun entweder die Methode aktualisiere mit einer Handlung überschreiben (Tk-BAlten verändern) oder einen Thread starten, der Zugriff auf f hat und somit jede Sekunde f.retrsize und f.filesize auslesen kann oder aber ... denk dir selbst was aus

Die Methode __del__ sichert, dass die Datei automatisch bei Programmende geschlossen wird, fals dies vergessen wurde.
Milan