从FTP python读取缓冲区中的文件

从FTP python读取缓冲区中的文件,python,ftp,stream,ftplib,Python,Ftp,Stream,Ftplib,我正在尝试从FTP服务器读取文件。该文件是.gz文件。我想知道在套接字打开时是否可以对此文件执行操作。我试着按照上面两个StackOverflow问题中提到的内容去做,但没有成功 我知道如何在下载的文件上提取数据/工作,但我不确定是否可以在运行中提取数据/工作。是否有方法连接到站点,在缓冲区中获取数据,可能进行一些数据提取并退出 尝试StringIO时,我遇到了错误: >>> from ftplib import FTP >>> from StringIO i

我正在尝试从FTP服务器读取文件。该文件是
.gz
文件。我想知道在套接字打开时是否可以对此文件执行操作。我试着按照上面两个StackOverflow问题中提到的内容去做,但没有成功

我知道如何在下载的文件上提取数据/工作,但我不确定是否可以在运行中提取数据/工作。是否有方法连接到站点,在缓冲区中获取数据,可能进行一些数据提取并退出

尝试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
>>从ftplib导入FTP
>>>从StringIO导入StringIO
>>>ftp=ftp('ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/PMC-ids.csv.gz')
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
ftp=ftp('ftp://ftp.ncbi.nlm.nih.gov/pub/pmc/PMC-ids.csv.gz')
文件“C:\Python27\lib\ftplib.py”,第117行,在_init中__
self.connect(主机)
文件“C:\Python27\lib\ftplib.py”,第132行,在connect中
self.sock=socket.create_连接((self.host,self.port),self.timeout)
文件“C:\Python27\lib\socket.py”,第553行,位于create\u connection中
对于getaddrinfo(主机、端口、0、SOCK_流)中的res:
gaierror:[Errno 11004]getaddrinfo失败
我只需要知道如何将数据放入某个变量中并在其上循环,直到读取FTP中的文件


我感谢你的时间和帮助。谢谢

我可以想出两种简单的方法来使用FTP下载文件并将其存储在本地:

  • 使用
    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()
    
  • 使用
    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
    

    逐行打印您的文件。

    这是不可能的。要在服务器上处理数据,您需要具有某种执行权限,无论是针对要发送的shell脚本还是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()
    

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

    确保首先登录到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()
    

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

    您需要将文件读入本地缓冲区(如read())还是使用FTP命令远程操作它?我想使用FTP远程操作它。如果我错了,请纠正我,但如果我将其读入本地缓冲区,这是否意味着下载文件?我的意思是,您希望将数据从FTP服务器传输到您的PC,然后使用它,对吗?(这就是您链接的SO问题中发生的情况)很抱歉造成混淆,但我不想在我的电脑上传输服务器上的数据。那么,您想在服务器上处理数据,然后在您的电脑上传输结果吗?还是怎样请澄清。谢谢你的回答。我有一个简单的问题,这会不会在我的电脑上下载数据?如果不是它保存数据的位置?它保存在内存中,在一个名为data的字符串中(或者如果一直都是未压缩的)。那么,保存数据的最后一个变量将是未压缩的,对吗?我不知道为什么,但是,如果要用BytesIO替换StringIO,在使用python3.4时将其截断,实际上不需要使用
    handle\u binary
    函数。只需分别使用
    callback=data.append
    callback=sio.write
    。在仔细阅读Kyle和Stefano之间交换的评论后,在问题的正下方,我为否决这个答案而道歉。然而,凯尔想问的似乎并不是他实际问的。如果你把斯蒂法诺的回答作为对原始问题的回答来阅读,那么它似乎不是真的。在任何情况下,如果Stefano澄清了他的答案(并编辑了答案,让我收回我的反对票),我会很高兴进行修正。我可能错了,但在选项1中,如果读取二进制文件需要多个块,它不会用下一个块覆盖文件吗?不应该将open设置为
    'ab'
    而不是
    'wb'
    @TomBusby,不,
    'wb'
    很好。Python中传递的参数是渴望的(按值调用)。传递给
    retrbinary
    方法的回调只是第二个参数。它被急切地计算,因此,
    open(…,'wb')
    只计算一次,返回文件对象的
    write
    方法是传递给
    retrbinary
    的回调。文件只打开一次进行写入,而不是像您所想的那样每次调用回调。