13

我正在尝试从 FTP 服务器读取文件。该文件是一个.gz文件。我想知道我是否可以在套接字打开时对此文件执行操作。我尝试遵循两个 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:\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

我只需要知道如何将数据放入某个变量并在其上循环,直到读取来自 FTP 的文件。

感谢您的时间和帮助。谢谢!

4

3 回答 3

29

确保首先登录到 ftp 服务器。在此之后,使用retrbinarywhich 以二进制模式拉取文件。它对文件的每个块使用回调。您可以使用它来将其加载到字符串中。

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

实际上,动态解压缩会好得多,但我看不到使用内置库的方法(至少不容易)。

于 2013-09-12T20:07:31.037 回答
6

我可以想到两种简单的方法来使用 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

它逐行打印您的文件。

于 2013-09-12T19:37:22.943 回答
0

这是不可能的。要在服务器上处理数据,您需要具有某种执行权限,无论是您要发送的 shell 脚本还是 SQL 访问权限。

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

特别是,我认为第三个是唯一的零努力解决方案。

于 2013-09-12T19:40:01.647 回答