Чтение файла в буфере из FTP python

Я пытаюсь прочитать файл с FTP-сервера. Файл . Я хотел бы знать, могу ли я выполнять действия с этим файлом, пока сокет открыт. Я попытался следовать тому, что было упомянуто в двух вопросах StackOverflow на чтение файлов без записи на диск и чтение файлов с FTP без скачивания но не удалось.

Я знаю, как извлечь данные / работать с загруженным файлом, но я не уверен, что могу это сделать на летать. Есть ли способ подключиться к сайту, получить данные в буфере, возможно, сделать некоторое извлечение данных и выйти?

при попытке StringIO я получил ошибку:

>>> 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 "<pyshell#2>", line 1, in <module>
ftp = FTP('ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/PMC-ids.csv.gz')
File "C:Python27libftplib.py", line 117, in __init__
self.connect(host)
File "C:Python27libftplib.py", line 132, in connect
self.sock = socket.create_connection((self.host, self.port), self.timeout)
File "C:Python27libsocket.py", line 553, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
gaierror: [Errno 11004] getaddrinfo failed

мне просто нужно знать, как я могу получить данные в некоторую переменную и цикл на ней, пока файл с FTP не будет прочитан.

Я ценю ваше время и помощь. Спасибо!

3 ответов


убедитесь, что сначала войдите на ftp-сервер. После этого используйте retrbinary, который тянет файл в двоичном режиме. Он использует обратный вызов для каждого фрагмента файла. Вы можете использовать это, чтобы загрузить его в строку.

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)

бонусные баллы: как насчет того, чтобы распаковать строку, пока мы здесь?

легкий режим, используя строку данных выше

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

немного лучше, полное решение:

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()

на самом деле, было бы гораздо лучше, чтобы распаковка на лету, но я не вижу способа сделать это со встроенными библиотеками (по крайней мере, не легко).


есть два простых способа, которые я могу придумать, чтобы загрузить файл с помощью FTP и сохранить его локально:

  1. используя 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. используя urllib

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

если вы не хотите загружать и хранить его в файл, но вы хотите обрабатывать его постепенно, как это происходит, я предлагаю использовать urllib2:

from urllib2 import urlopen

u = urlopen("ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/readme.txt")

for line in u:
   print line

который печатает ваш файл строка за строкой.


это невозможно. Для обработки данных на сервере необходимо иметь какие-то разрешения на выполнение, будь то для сценария оболочки или SQL access.

FTP-это чистая передача файлов, выполнение не допускается. Вам нужно будет либо включить SSH-доступ, загрузить данные в базу данных и получить доступ к ней с запросами, либо загрузить файл с помощью urllib затем обработайте его локально, вот так:

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

в частности, я думаю, что третий-это единственное нулевое усилие решение.