Lee un archivo en búfer desde FTP python

Estoy tratando de leer un archivo de un servidor FTP. El archivo es un archivo .gz . Me gustaría saber si puedo realizar acciones en este archivo mientras el socket está abierto. Intenté seguir lo que se mencionó en dos preguntas de StackOverflow sobre la lectura de archivos sin escribir en el disco y la lectura de archivos desde FTP sin descargar, pero no tuve éxito.

Sé cómo extraer datos / trabajo en el archivo descargado, pero no estoy seguro de poder hacerlo sobre la marcha. ¿Hay alguna forma de conectarse al sitio, obtener datos en un búfer, posiblemente extraer algo y salir?

Al intentar StringIO me salió el error:

 >>> from ftplib import FTP >>> from StringIO import StringIO >>> ftp = FTP('ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/PMC-ids.csv.gz') Traceback (most recent call last): File "", line 1, in  ftp = FTP('ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/PMC-ids.csv.gz') File "C:\Python27\lib\ftplib.py", line 117, in __init__ self.connect(host) File "C:\Python27\lib\ftplib.py", line 132, in connect self.sock = socket.create_connection((self.host, self.port), self.timeout) File "C:\Python27\lib\socket.py", line 553, in create_connection for res in getaddrinfo(host, port, 0, SOCK_STREAM): gaierror: [Errno 11004] getaddrinfo failed 

Solo necesito saber cómo puedo obtener datos en alguna variable y hacer un bucle hasta que se lea el archivo de FTP.

Aprecio tu tiempo y ayuda. ¡Gracias!

Asegúrese de iniciar sesión en el servidor ftp primero. Después de esto, use retrbinary que extrae el archivo en modo binario. Utiliza una callback en cada parte del archivo. Puedes usar esto para cargarlo en una cadena.

 from ftplib import FTP ftp = FTP('ftp.ncbi.nlm.nih.gov') ftp.login() # Username: anonymous password: anonymous@ # Setup a cheap way to catch the data (could use StringIO too) data = [] def handle_binary(more_data): data.append(more_data) resp = ftp.retrbinary("RETR pub/pmc/PMC-ids.csv.gz", callback=handle_binary) data = "".join(data) 

Puntos extra: ¿qué tal si descomprimimos la cuerda mientras estamos en eso?

Modo fácil, usando la cadena de datos de arriba

 import gzip import StringIO zippy = gzip.GzipFile(fileobj=StringIO.StringIO(data)) uncompressed_data = zippy.read() 

Un poco mejor, la solución completa :

 from ftplib import FTP import gzip import StringIO ftp = FTP('ftp.ncbi.nlm.nih.gov') ftp.login() # Username: anonymous password: anonymous@ sio = StringIO.StringIO() def handle_binary(more_data): sio.write(more_data) resp = ftp.retrbinary("RETR pub/pmc/PMC-ids.csv.gz", callback=handle_binary) sio.seek(0) # Go back to the start zippy = gzip.GzipFile(fileobj=sio) uncompressed = zippy.read() 

En realidad, sería mucho mejor descomprimir sobre la marcha, pero no veo una manera de hacerlo con las bibliotecas integradas (al menos no fácilmente).

Hay dos formas sencillas en las que puedo pensar para descargar un archivo mediante FTP y almacenarlo localmente:

  1. Utilizando ftplib :

     from ftplib import FTP ftp = FTP('ftp.ncbi.nlm.nih.gov') ftp.login() ftp.cwd('pub/pmc') ftp.retrbinary('RETR PMC-ids.csv.gz', open('PMC-ids.csv.gz', 'wb').write) ftp.quit() 
  2. Usando urllib

     from urllib import urlretrieve urlretrieve("ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/PMC-ids.csv.gz", "PMC-ids.csv.gz") 

Si no desea descargarlo y almacenarlo en un archivo, pero desea procesarlo gradualmente, sugiero usar urllib2 :

 from urllib2 import urlopen u = urlopen("ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/readme.txt") for line in u: print line 

que imprime su archivo línea por línea.

Eso no es posible. Para procesar los datos en el servidor, debe tener algún tipo de permisos de ejecución, ya sea para un script de shell que enviaría o para acceder a SQL.

FTP es pura transferencia de archivos, no se permite la ejecución. Necesitará habilitar el acceso SSH, cargar los datos en una base de datos y acceder a ellos con consultas o descargar el archivo con urllib y procesarlo localmente, como esto:

 import urllib handle = urllib.urlopen('ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/PMC-ids.csv.gz') # Use data, maybe: buffer = handle.read() 

En particular, creo que la tercera es la única solución de esfuerzo cero.