2012-06-26 16 views
19

Estoy tratando de leer archivos usando ftplib de Python sin escribirlos. Algo aproximadamente equivalente a:¿Es posible leer archivos FTP sin escribirlos usando Python?

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

pero mediante FTP.

me trataron:

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

pero esto no funciona. Los únicos ejemplos en los documentos implican escribir archivos usando el formato ftp.retrbinary('RETR README', open('README', 'wb').write). ¿Es posible leer archivos ftp sin escribir primero?

+0

Una objeción terminológica: la respuesta a su pregunta tal como la ha redactado es no, porque "descargar" significa "transferencia desde el servidor", no "guardar en el disco". El ejemplo 'urllib' que le diste _does_ descarga el archivo; simplemente no lo guarda en el disco. – senderle

+0

Suena como. ¿Es posible leer un libro sin abrirlo? FTP está diseñado para transferir archivos. Entonces, el protocolo ftp no tiene acciones que impliquen leer, ejecutar o abrir un archivo. Otro tema de stackoverlow plantea la misma pregunta para java. FTP envía el archivo como un flujo de bits. Por lo tanto, podría ser posible leer y manejar el archivo durante la descarga. http://stackoverflow.com/questions/7690320/how-to-read-files-from-ftp-without-download-them – Erik

+0

Sí, me di cuenta de que lo redacté mal después de publicarlo ... editaré ahora. – aensm

Respuesta

35

Bueno, usted tiene la respuesta justo delante de usted: El método retrbinary acepta como segundo parámetro una referencia a una función que se llama siempre que el contenido del archivo se recupera de la conexión ftp.

Aquí está un ejemplo sencillo:

#!/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) 

Debe implementar writeFunc por lo que en realidad se anexa los datos leídos a una variable interna, algo como esto, que utiliza un objeto invocable:

#!/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 

Actualización: Me di cuenta de que hay un módulo en la biblioteca estándar de Python que es para este tipo de cosas, StringIO:

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

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

print r.getvalue() 
+2

¡Impresionante, gracias! No me di cuenta de que la devolución de llamada podría ser una función definida por el usuario – aensm

+1

Para Python 3, retrbinary requiere BytesIO, porque devuelve bytes, no cadena. Si quieres StringIO, prueba ftp.retrlines() –

Cuestiones relacionadas