使用Python的FTP库获取文件

3 投票
3 回答
8246 浏览
提问于 2025-04-16 08:02

这是我在这里的第一篇帖子,我很高兴能成为这个社区的一员。我有一个比较普通的问题想问,但这个问题让我很烦恼,所以希望能找到答案。

我正在尝试使用Python的FTPLIB模块来获取一个二进制文件。

我直接在解释器中输入的代码是这样的:

>>> from ftplib import FTP 

>>> ftp = FTP('xxx.xx.xx.x')  # IP of target device

>>> ftp.login()

>>> file = "foobar.xyz" # target file 

>>> ftp.retrbinary("RETR " + file, open('filez.txt', 'wb').write)

虽然某些功能可以正常工作(我可以查看设备上的所有文件,获取FTP服务器应用的欢迎信息,甚至可以重命名文件),但当我尝试执行上面的最后一个命令时,我得到了

    error_perm                                Traceback (most recent call last)

/Users/user_name/<ipython console> in <module>()

/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in retrlines(self, cmd, callback)
    419         if callback is None: callback = print_line
    420         resp = self.sendcmd('TYPE A')
--> 421         conn = self.transfercmd(cmd)
    422         fp = conn.makefile('rb')
    423         while 1:

/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in transfercmd(self, cmd, rest)
    358     def transfercmd(self, cmd, rest=None):
    359         """Like ntransfercmd() but returns only the socket."""
--> 360         return self.ntransfercmd(cmd, rest)[0]
    361 
    362     def login(self, user = '', passwd = '', acct = ''):

/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in ntransfercmd(self, cmd, rest)
    327             if rest is not None:
    328                 self.sendcmd("REST %s" % rest)
--> 329             resp = self.sendcmd(cmd)
    330             # Some servers apparently send a 200 reply to

    331             # a LIST or STOR command, before the 150 reply


/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in sendcmd(self, cmd)
    241         '''Send a command and return the response.'''
    242         self.putcmd(cmd)
--> 243         return self.getresp()
    244 
    245     def voidcmd(self, cmd):

/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in getresp(self)
    216             raise error_temp, resp
    217         if c == '5':
--> 218             raise error_perm, resp
    219         raise error_proto, resp
    220 

error_perm: 502 Command not implemented.

我查看了ftplib的源代码,但我在这方面的编程经验比较有限,因为我通常用Python做数学计算,从来没有接触过FTP。

所以,如果有人能给我一些解决方案的想法,那将是一个很大的帮助。或者,如果你能建议用其他语言的解决方案路径,那也会很有帮助。

3 个回答

0

对我来说一切正常,试试其他服务器吧(我用的是一个Debian的FTP服务器进行测试):

ftp = FTP('xx.xx.xx.xx')

ftp.login()

'230 登录成功.'

file="robots.txt"

ftp.retrlines("RETR "+file, open('filez.txt', 'wb').write)

'226 文件发送成功.'

1

如果你的情况真的这么简单,那就没必要使用ftplib这个模块了。urllib.urlretrieve就能满足你的需求。例如:

import urllib
urllib.urlretrieve('ftp://xxx.xx.xx.x/foobar.xyz', filename='filez.txt')

注意:在Python 3.x中,这个功能是urllib.request.urlretrieve

如果FTP服务器不是匿名的,你只需要在网址字符串中指定用户名和密码,就像平常那样(例如:ftp://user:password@server/path/to/file)。当然,FTP协议会以明文形式发送密码,而你又把用户名和密码写在了脚本里,所以这样做在安全上有很多问题,但无论你用哪个库,这个问题都是存在的。

8

看起来你是在匿名登录,也就是在ftp.login()里没有输入用户名和密码,所以你遇到了权限错误。试试用下面的方式登录:

ftp.login(user='foo', passwd='bar')

来试试。

补充:这里有一个简单的ftplib使用示例(很简单,没有错误处理):

#!/usr/bin/env python

from ftplib import FTP

HOST   = "localhost"
UNAME  = "foo"
PASSWD = "bar"
DIR    = "pub"
FILE   = "test.test"

def download_cb(block):
    file.write(block)

ftp = FTP(HOST)
ftp.login(user=UNAME, passwd=PASSWD)
ftp.cwd(DIR)

file = open(FILE, "wb")
ftp.retrbinary("RETR " + FILE, download_cb)
file.close()
ftp.close()

注意:如果retrbinary不工作,你也可以在调用它之前,先用ftp.sendcmd("TYPE I")来明确设置为二进制模式。这种情况不常见,但可能对某些特殊的ftp服务器有帮助。

撰写回答