使用Python的FTP库来检索文件

时间:2010-12-04 19:44:49

标签: python sockets ftp

这是我在这里发表的第一篇文章,所以我很高兴成为社区的一员。我有一个相当平凡的问题,但这是一个相当烦人的问题,所以我希望能找到答案。

所以我正在尝试使用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 :(得分: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服务器。

答案 1 :(得分:1)

如果您的情况非常简单,则无需使用ftplib modlue。 urllib.urlretrieve会做你需要的。 E.g:

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

注意:顺便说一下,这将是python 3.x中的urllib.request.urlretrieve ......

如果ftp服务器不是匿名的,您只需像往常一样在url字符串中指定用户名和密码(例如ftp://user:password@server/path/to/file)。当然,ftp协议以纯文本形式发送密码,并且您已将用户名和密码存储在脚本中,因此由于多种原因这是不安全的,但无论您使用哪个库,都是如此。

答案 2 :(得分:0)

对我来说工作正常,尝试使用其他服务器(我已经使用debian ftp服务器测试过。):

  

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

     

ftp.login()

     

'230登录成功。'

     

文件= “robots.txt的”

     

ftp.retrlines(“RETR”+ file,open('filez.txt','wb')。write)

     

'226文件发送确定。'