web-dev-qa-db-fra.com

Est-il possible de lire des fichiers FTP sans les écrire en utilisant Python?

J'essaie de lire des fichiers en utilisant ftplib de Python sans les écrire. Quelque chose à peu près équivalent à:

def get_page(url):
    try:
        return urllib.urlopen(url).read()
    except:
        return ""

mais en utilisant FTP.

J'ai essayé:

def get_page(path):
    try:
        ftp = FTP('ftp.site.com', 'anonymous', 'passwd')
        return ftp.retrbinary('RETR '+path, open('page').read())
    except:
        return ''

mais cela ne fonctionne pas. Les seuls exemples dans la documentation impliquent l'écriture de fichiers en utilisant le format ftp.retrbinary('RETR README', open('README', 'wb').write). Est-il possible de lire des fichiers ftp sans écrire d'abord?

28
aensm

Eh bien, vous avez la réponse juste devant vous: la méthode rétrbinaire accepte comme deuxième paramètre une référence à une fonction qui est appelée chaque fois que le contenu du fichier est récupéré de la connexion ftp.

Voici un exemple simple:

#!/usr/bin/env python
from ftplib import FTP

def writeFunc(s):
  print "Read: " + s

ftp = FTP('ftp.kernel.org') 
ftp.login()
ftp.retrbinary('RETR /pub/README_ABOUT_BZ2_FILES', writeFunc)

Vous devez implémenter writeFunc pour qu'il ajoute réellement les données lues à une variable interne, quelque chose comme ceci, qui utilise un objet appelable:

#!/usr/bin/env python
from ftplib import FTP

class Reader:
  def __init__(self):
    self.data = ""
  def __call__(self,s):
     self.data += s

ftp = FTP('ftp.kernel.org') 
ftp.login()
r = Reader()
ftp.retrbinary('RETR /pub/README_ABOUT_BZ2_FILES', r)

print r.data

pdate: J'ai réalisé qu'il y a un module dans la bibliothèque standard Python qui est destiné à ce genre de choses, StringIO:

#!/usr/bin/env python
from ftplib import FTP
from io import StringIO

ftp = FTP('ftp.kernel.org') 
ftp.login()
r = StringIO()
ftp.retrbinary('RETR /pub/README_ABOUT_BZ2_FILES', r.write)

print r.getvalue()

Mise à jour 2: StringIO a été intégré dans io. Incorporated @ TimRichardson's comment .:

47
daniel kullmann