我正在尝试从FTP服务器读取文件。该文件是.gz
文件。我想知道在套接字打开时是否可以对此文件执行操作。我尝试按照reading files without writing to disk和reading files from FTP without downloading上的两个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
我只需要知道如何将数据放入某个变量并在其上循环,直到读取FTP文件为止。
感谢您的时间和帮助。谢谢!
答案 0 :(得分:24)
请务必先登录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()
实际上,动态解压缩会好得多,但我没有办法用内置库(至少不容易)做到这一点。
答案 1 :(得分:5)
我可以通过两种简单的方法来使用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
逐行打印文件。
答案 2 :(得分: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()
特别是,我认为第三个是唯一的零努力解决方案。