【问题标题】:Getting an error running FTP.retrbinary to retrieve a file运行 FTP.retrbinary 检索文件时出错
【发布时间】:2015-02-15 01:07:12
【问题描述】:

我正在使用 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 ?

知道是什么导致了错误吗?

【问题讨论】:

    标签: python ftp ftplib


    【解决方案1】:

    如果响应的状态码以“5”开头,ftplib 会引发错误。这意味着服务器正在返回一个 5xx 错误:

    0.5.1 500内部服务器错误

    服务器遇到了一个意外情况,阻止了它 满足请求。

    10.5.2 501 未实施

    服务器不支持实现 要求。这是服务器不响应时的适当响应 识别请求方法并且无法支持它 任何资源。

    10.5.3 502 网关错误

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

    10.5.4 503服务不可用

    服务器当前无法处理请求,因为 服务器临时超载或维护。含义是 这是一种暂时的情况,经过一段时间后会得到缓解 延迟。如果已知,延迟的长度可以在一个 重试后标头。如果没有给出 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 命令:'RETR 文件名'。

    但是你写了这个:

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

    这将产生如下内容:

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

    你需要在'RETR'之后添加一个空格。

    用python创建你自己的ftp服务器

    顺便说一句,您可以编写一个简短的 python 程序来充当 ftp 服务器。先安装模块pyftpdlib

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

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

    $ pip install pyftpdlib
    

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

    这是 ftp 服务器在 python 中的样子:

    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 目录中。然后通过运行 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$ 
    

    【讨论】:

    • 好的,就是这样。谢谢。我想我真的必须更加注意我的语法。总是简单的东西。再次感谢!
    • @Marlone,不客气!有一种更好的方法来构造字符串:.................................................. ................ftp_cmd = "RETR {}".format(filename) 然后ftp.retrbinary(ftp_cmd, localfile.write, 1024)。请参阅此处的 format() 示例:docs.python.org/3/library/string.html#format-examples。您还可以为您的 ftp 服务器使用 python 程序。在我的帖子末尾查看方法。
    • 太棒了,感谢您提供有关创建 ftp 服务器的其他信息,猜猜这是我的下一个项目!
    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 2014-08-18
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多