Seite 1 von 1

ftplib: ftp.retrbinary-Callback

Verfasst: Dienstag 23. Januar 2007, 22:29
von to.ni
Hallo zusammen,

schon fast peinlich, hier schon wieder das Forum bemühen zu müssen... :oops:

Aber ich habe eine Frage zur Callback-Funktionalität der retrbinary-Methode:
In der Dokumentation steht:

Code: Alles auswählen

retrbinary(command, callback[, maxblocksize[, rest]])
In den meisten Beispielen, die ich gefunden habe wird als Callback einfach fh.write angegeben, um die empfangenen Daten zu speichern. Ich würde aber gerne eine Fortschrittsanzeige realisieren, die anzeigt wie viele Daten schon empfangen wurden.
Dazu hätte ich eine eigene Funktion definiert und diese als Callback angegeben:

Code: Alles auswählen

ftp.retrbinary("RETR test.jpg", transfer_callback)
Leider kann ich da aber ja keine Argumente übergeben... z.B. den Filehandler, der zu speichernden Datei?

wieder mal danke für eure hilfe...

Verfasst: Dienstag 23. Januar 2007, 22:47
von Mephisto
Hi,

Wenn du Python 2.5 benutzt kannst du das so machen:

Code: Alles auswählen

from functools import partial

def transfer_callback(fileobj, block):
    pass

fileobj = open('test.jpg', 'wb')
ftp.retrbinary("RETR test.jpg", partial(transfer_callback, fileobj))
partial gibt eine Funktion zurück, die sich genau wie transfer_callback verhält, ausser dass sie vor dem eigentlichen Aufruf von "transfer_callback" als ersten Parameter das "fileobj" einfuegt. (Ich hoffe das konnte man verstehen, ansonsten steht in der Doku mehr dazu :))

Vor Python2.5 kann man "lambda"s verwenden

Code: Alles auswählen


def transfer_callback(fileobj, block):
    pass

fileobj = open('test.jpg', 'wb')
ftp.retrbinary("RETR test.jpg", lambda block: transfer_callback(fileobj, block))
HTH

Grüsse, Mephisto

Verfasst: Dienstag 23. Januar 2007, 23:04
von gerold
Und hier eine etwas längere Version. :-)

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import ftplib
from StringIO import StringIO


class ByteContainer(StringIO):
   
    def __init__(self, buf = ""):
        StringIO.__init__(self, buf)
        self.bytecounter = 0
   
    def write(self, bytestring):
        self.bytecounter += len(bytestring)
        print "%i Bytes transfered." % self.bytecounter
        file.write(self, bytestring)

f = ByteContainer()
ftp = ftplib.FTP()
ftp.connect("host", 21)
ftp.login("user", "pass")
ftp.set_pasv(True)
ftp.retrbinary("RETR bild.jpg", f.write)
ftp.quit()

print repr(f.getvalue())
mfg
Gerold
:-)

Verfasst: Dienstag 23. Januar 2007, 23:18
von gerold
...das geht natürlich auch direkt mit dem ``file``-Objekt.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import ftplib
import time


class ByteContainer(file):
    
    def __init__(self, name, mode = "wb"):
        file.__init__(self, name, mode)
        self.bytecounter = 0
    
    def write(self, bytestring):
        self.bytecounter += len(bytestring)
        print "%i Bytes transfered." % self.bytecounter
        file.write(self, bytestring)
    

f = ByteContainer("bild.jpg", "wb")
ftp = ftplib.FTP()
ftp.connect("host", 21)
time.sleep(0.2)
ftp.login("user", "pass")
time.sleep(0.2)
ftp.retrbinary("RETR bild.jpg", f.write)
ftp.quit()

f.close()
mfg
Gerold
:-)

Verfasst: Donnerstag 25. Januar 2007, 15:36
von to.ni
Nochmal hallo,

merci für eure Vorschläge. Inzwischen klappt der Download mit Übertragungsanzeige ;-)

Grüße tobi