运行FTP.retrbinary以检索文件时出错

时间:2015-02-15 01:07:13

标签: python ftp ftplib

我使用pythons ftplib尝试从远程服务器(练习项目)中检索文件。我在发送文件时没有遇到任何问题,但在尝试检索时遇到错误。我使用的是python 3.这是我的代码:

from ftplib import FTP

user = 'myusername'
passw = 'mypassw'
url = input('FTP url: ').lower().strip()
ftp = FTP(url)      #connect to the host, default port
ftp.login(user, passw) # enters login info

def getfile():
    ftp.retrlines('LIST')   # List directory contents
    filename = input('Name of file: ')
    localfile = open(filename, 'wb')
    ftp.retrbinary('RETR' + filename, localfile.write, 1024)
    localfile.close()

getfile()

这是我得到的错误:

Traceback (most recent call last):
  File "C:\Users\User\Desktop\School\python\ftpget.py", line 16, in <module>
    getfile()
  File "C:\Users\User\Desktop\School\python\ftpget.py", line 13, in getfile
    ftp.retrbinary('RETR' + filename, localfile.write, 1024)
  File "C:\Python34\lib\ftplib.py", line 441, in retrbinary
    with self.transfercmd(cmd, rest) as conn:
  File "C:\Python34\lib\ftplib.py", line 398, in transfercmd
    return self.ntransfercmd(cmd, rest)[0]
  File "C:\Python34\lib\ftplib.py", line 364, in ntransfercmd
    resp = self.sendcmd(cmd)
  File "C:\Python34\lib\ftplib.py", line 272, in sendcmd
    return self.getresp()
  File "C:\Python34\lib\ftplib.py", line 245, in getresp
    raise error_perm(resp)
ftplib.error_perm: 500 ?

知道造成错误的原因是什么?

1 个答案:

答案 0 :(得分:2)

如果响应的状态代码以“&#39; 5”开头,则

ftplib会引发错误。这意味着服务器返回5xx错误:

  

0.5.1 500 内部服务器错误

     

服务器遇到阻止它的意外情况   满足要求。

     

10.5.2 501 未实施

     

服务器不支持履行该功能所需的功能   请求。当服务器没有时,这是适当的响应   识别请求方法,并且无法支持它   任何资源。

     

10.5.3 502 Bad Gateway

     

服务器在充当网关或代理时收到无效   来自它在尝试实现时访问的上游服务器的响应   请求。

     

10.5.4 503 服务不可用

     

由于a,服务器当前无法处理请求   临时超载或维护服务器。这意味着   这是一个暂时的条件,一些后会缓解   延迟。如果已知,延迟的长度可以用a表示   Retry-After标头。如果没有给出Retry-After,客户端应该是   像处理500响应那样处理响应。

  Note: The existence of the 503 status code does not imply that a
  server must use it when becoming overloaded. Some servers may wish
  to simply refuse the connection.
     

10.5.5 504 网关超时

     

服务器在充当网关或代理时,没有收到   来自URI指定的上游服务器的及时响应(例如   HTTP,FTP,LDAP)或它需要的一些其他辅助服务器(例如DNS)   尝试完成请求时访问。

  Note: Note to implementors: some deployed proxies are known to
  return 400 or 500 when DNS lookups time out.
     

10.5.6 505 不支持HTTP版

     

服务器不支持或拒绝支持HTTP协议   请求消息中使用的版本。服务器正在指示   它无法或不愿意使用相同的方式完成请求   主要版本作为客户端,如3.1节所述,除了   有这个错误消息。响应应该包含一个实体   描述为什么不支持该版本以及其他协议   该服务器支持。

根据ftp docs

  

FTP.retrbinary (命令,回调[,maxblocksize [,rest]])
  检索一个   文件以二进制传输模式。命令应该是适当的RETR   命令:&#39; RETR文件名&#39;。

但你写了这个:

ftp.retrbinary('RETR' + filename, localfile.write, 1024)

会产生这样的东西:

ftp.retrbinary('RETRdog.jpg', localfile.write, 1024)

您需要在&#39; RETR&#39;。

之后添加空格

使用python

创建自己的ftp服务器

顺便说一句,你可以写一个短的python程序,它将充当ftp服务器。首先安装模块pyftpdlib

$ pip3.4 install pyftpdlib  #See note on 3.4 below

如果你的系统上只有一个版本的python,你可以写:

$ pip install pyftpdlib

如果您的计算机上有多个版本的python,请使用正确的版本号替换3.4。您指定的版本号是pyftpdlib模块将安装的python版本。

以下是python中的ftp服务器:

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

my_authorizer = DummyAuthorizer()
my_authorizer.add_user(
    username = '7stud', 
    password = '1234', 
    homedir = '.', 
    perm='elrw'  #permissions: 'e'->change dir, 'l'->list files, 'r'->retrieve files, 'w'->store a file to the server
)

my_handler = FTPHandler
my_handler.authorizer = my_authorizer

port = 2121
my_handler.banner = "You connected to my ftp server on port: {}".format(port)

address = ('localhost', port)
server = FTPServer(address, my_handler)

server.max_cons = 256
server.max_cons_per_ip = 5

server.serve_forever()

pyftpdlib文档和教程hereadd_user()和描述here的权限。

然后,您可以为服务器创建目录:

$ mkdir ftp_server
$ cd ftp_server
$ touch my_ftp_server.py

将上面的代码放入文件my_ftp_server.py。然后将一些文件添加到要练习的ftp_server目录中并下载&#39;。然后运行my_ftp_server.py启动服务器。

在另一个终端窗口中,将目录切换到包含python程序的目录:

$ cd python_programs

然后对您的ftp客户端程序进行一些小的更改:

from ftplib import FTP

def getfile(conn):  #It's good practice not to refer to global variables in your functions.
                    #Instead, pass in any values your function needs as arguments.
    conn.retrlines('LIST')   # List directory contents

    filename = input('Name of file: ')
    localfile = open(filename, 'wb')
    ftp_command = 'RETR {}'.format(filename)

    conn.retrbinary(ftp_command, localfile.write, 1024)

    localfile.close()

user = '7stud'
passw = '1234'
port = 2121

url = input('FTP url: ').lower().strip()

ftp = FTP()
ftp.connect(url, port)
ftp.login(user, passw) 
getfile(ftp)
ftp.quit()

这是您的ftp客户端程序的示例运行:

~/python_programs$ python3.4 ftp_client.py 
FTP url: localhost

drwxr-xr-x   4 7stud    staff         136 Feb 11 09:07 cgi-bin
-rw-r--r--   1 7stud    staff        3446 Jun 08  2013 client_socket.py
-rw-r--r--   1 7stud    staff         680 Feb 15 03:03 ftp_server.py
-rw-r--r--   1 7stud    staff         721 Feb 12 03:01 http_server.py
-rw-r--r--   1 7stud    staff         498 Jan 01 07:10 index.html
-rw-r--r--   1 7stud    staff          68 Jan 01 05:03 oneliner.py
-rw-r--r--   1 7stud    staff         954 Feb 11 09:05 socket_server.py
-rw-r--r--   1 7stud    staff           0 Feb 15 02:50 test.png

Name of file: test.png

~/python_programs$ ls *.png
bar_freq.png  example.png   test.png

~/python_programs$