代码之家  ›  专栏  ›  技术社区  ›  Marlone

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

  •  2
  • Marlone  · 技术社区  · 10 年前

    我正在使用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 回复  |  直到 10 年前
        1
  •  3
  •   7stud    10 年前

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

    0.5.1 500 内部服务器错误

    服务器遇到意外情况,无法 完成请求。

    10.5.2 501 未实施

    服务器不支持实现 要求当服务器没有 识别请求方法,并且无法支持 任何资源。

    10.5.3 502 坏网关

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

    10.5.4 503 服务不可用

    服务器当前无法处理请求,原因是 服务器的临时过载或维护。其含义是 这是一种暂时的情况,在一些 延迟如果已知,延迟长度可在 在标头之后重试。如果未给出重试时间,则客户端应 按照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.重试二进制 (命令,回调[,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 文档和教程 here . add_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$