# 21.13. `ftplib` — FTP 协议客户端

源代码： Lib/ftplib.py

本模块定义了 `FTP` 类和一些相关项目。`FTP` 类实现了 FTP 协议的客户端。可以用该类编写 Python 程序，执行各种自动化的 FTP 任务，如镜像其他 FTP 服务器。`urllib.request` 模块也用它来处理使用了 FTP 的 URL。关于 FTP（文件传输协议）的详情请参阅 Internet RFC 959。

以下是使用 `ftplib` 模块的会话示例:

    >>> from ftplib import FTP
    >>> ftp = FTP('ftp.debian.org')     # connect to host, default port
    >>> ftp.login()                     # user anonymous, passwd anonymous@
    '230 Login successful.'
    >>> ftp.cwd('debian')               # change into "debian" directory
    >>> ftp.retrlines('LIST')           # list directory contents
    -rw-rw-r--    1 1176     1176         1063 Jun 15 10:18 README
    ...
    drwxr-sr-x    5 1176     1176         4096 Dec 19  2000 pool
    drwxr-sr-x    4 1176     1176         4096 Nov 17  2008 project
    drwxr-xr-x    3 1176     1176         4096 Oct 10  2012 tools
    '226 Directory send OK.'
    >>> ftp.retrbinary('RETR README', open('README', 'wb').write)
    '226 Transfer complete.'
    >>> ftp.quit()

这个模块定义了以下内容：

class `ftplib.``FTP`(host='', user='', passwd='', acct='', timeout=None, source_address=None)

  Return a new instance of the `FTP` class. When host is given, the method call `connect(host)` is made. When user is given, additionally the method call `login(user, passwd, acct)` is made (where passwd and acct default to the empty string when not given). The optional timeout parameter specifies a timeout in seconds for blocking operations like the connection attempt (if is not specified, the global default timeout setting will be used). source_address is a 2-tuple `(host, port)` for the socket to bind to as its source address before connecting.

  `FTP` 类支持 `with` 语句，例如：

      >>> from ftplib import FTP
      >>> with FTP("ftp1.at.proftpd.org") as ftp:
      ...     ftp.login()
      ...     ftp.dir()
      ...
      '230 Anonymous login ok, restrictions apply.'
      dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 .
      dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 ..
      dr-xr-xr-x   5 ftp      ftp          4096 May  6 10:43 CentOS
      dr-xr-xr-x   3 ftp      ftp            18 Jul 10  2008 Fedora
      >>>

  在 3.2 版更改: 支持了 `with` 语句。

  在 3.3 版更改: 添加了 source_address 参数。

class `ftplib.``FTP_TLS`(host='', user='', passwd='', acct='', keyfile=None, certfile=None, context=None, timeout=None, source_address=None)

  一个 `FTP` 的子类，它为 FTP 添加了 TLS 支持，如 RFC 4217 所述。它将像通常一样连接到 21 端口，暗中保护在身份验证前的 FTP 控制连接。而保护数据连接需要用户明确调用 `prot_p()` 方法。context 是一个 `ssl.SSLContext` 对象，该对象可以将 SSL 配置选项、证书和私钥打包放入一个单独的（可以长久存在的）结构中。请阅读 安全考量 以获取最佳实践。

  keyfile 和 certfile 是可以代替 context 的传统方案，它们可以分别指向 PEM 格式的私钥和证书链文件，用于进行 SSL 连接。

  3.2 新版功能.

  在 3.3 版更改: 添加了 source_address 参数。

  在 3.4 版更改: 本类现在支持通过 `ssl.SSLContext.check_hostname` 和 服务器名称提示 （参阅 `ssl.HAS_SNI`）进行主机名检查。

  3.6 版后已移除: keyfile 和 certfile 已弃用并转而推荐 context。 请改用 `ssl.SSLContext.load_cert_chain()` 或让 `ssl.create_default_context()` 为你选择系统所信任的 CA 证书。

  以下是使用 `FTP_TLS` 类的会话示例:

      >>> ftps = FTP_TLS('ftp.pureftpd.org')
      >>> ftps.login()
      '230 Anonymous user logged in'
      >>> ftps.prot_p()
      '200 Data protection level set to "private"'
      >>> ftps.nlst()
      ['6jack', 'OpenBSD', 'antilink', 'blogbench', 'bsdcam', 'clockspeed', 'djbdns-jedi', 'docs', 'eaccelerator-jedi', 'favicon.ico', 'francotone', 'fugu', 'ignore', 'libpuzzle', 'metalog', 'minidentd', 'misc', 'mysql-udf-global-user-variables', 'php-jenkins-hash', 'php-skein-hash', 'php-webdav', 'phpaudit', 'phpbench', 'pincaster', 'ping', 'posto', 'pub', 'public', 'public_keys', 'pure-ftpd', 'qscan', 'qtc', 'sharedance', 'skycache', 'sound', 'tmp', 'ucarp']

exception `ftplib.``error_reply`

  从服务器收到意外答复时，将引发本异常。

exception `ftplib.``error_temp`

  收到表示临时错误的错误代码（响应代码在 400–499 范围内）时，将引发本异常。

exception `ftplib.``error_perm`

  收到表示永久性错误的错误代码（响应代码在 500–599 范围内）时，将引发本异常。

exception `ftplib.``error_proto`

  从服务器收到不符合 FTP 响应规范的答复，比如以数字 1–5 开头时，将引发本异常。

`ftplib.``all_errors`

  The set of all exceptions (as a tuple) that methods of `FTP` instances may raise as a result of problems with the FTP connection (as opposed to programming errors made by the caller). This set includes the four exceptions listed above as well as `OSError`.

参见

`netrc` 模块

  `.netrc` 文件格式解析器。FTP 客户端在响应用户之前，通常使用 `.netrc` 文件来加载用户认证信息。

## 21.13.1. FTP 对象

一些方法可以按照两种方式来使用：一种处理文本文件，另一种处理二进制文件。方法名称与相应的命令相同，文本版中命令后面跟着 `lines`，二进制版中命令后面跟着 `binary`。

`FTP` 实例具有下列方法:

`FTP.``set_debuglevel`(level)

  设置实例的调试级别，它控制着调试信息的数量。默认值 `0` 不产生调试信息。值 `1` 产生中等数量的调试信息，通常每个请求产生一行。大于或等于 `2` 的值产生的调试信息最多，FTP 控制连接上发送和接收的每一行都将被记录下来。

`FTP.``connect`(host='', port=0, timeout=None, source_address=None)

  连接到给定的主机和端口。默认端口号由 FTP 协议规范规定，为 `21`。偶尔才需要指定其他端口号。每个实例只应调用一次本函数，如果在创建实例时就传入了 host，则根本不应调用它。所有其他方法只能在建立连接后使用。可选参数 timeout 指定连接尝试的超时（以秒为单位）。如果没有传入 timeout，将使用全局默认超时设置。source_address 是一个 2 元组 `(host, port)`，套接字在连接前绑定它，作为其源地址。

  在 3.3 版更改: 添加了 source_address 参数。

`FTP.``getwelcome`()

  返回服务器发送的欢迎消息，作为连接开始的回复。（该消息有时包含与用户有关的免责声明或帮助信息。）

`FTP.``login`(user='anonymous', passwd='', acct='')

  以 user 的身份登录。passwd 和 acct 是可选参数，默认为空字符串。如果没有指定 user，则默认为 `'anonymous'`。如果 user 为 `'anonymous'`，那么默认的 passwd 是 `'anonymous@'`。连接建立后，每个实例只应调用一次本函数；如果在创建实例时传入了 host 和 user，则完全不应该调用本函数。在客户端登录后，才允许执行大多数 FTP 命令。acct 参数提供记账信息 (“accounting information”)；仅少数系统实现了该特性。

`FTP.``abort`()

  中止正在进行的文件传输。本方法并不总是有效，但值得一试。

`FTP.``sendcmd`(cmd)

  将一条简单的命令字符串发送到服务器，返回响应的字符串。

`FTP.``voidcmd`(cmd)

  将一条简单的命令字符串发送到服务器，并处理响应内容。如果收到的响应代码表示的是成功（代码范围 200–299），则不返回任何内容。否则将引发 `error_reply`。

`FTP.``retrbinary`(cmd, callback, blocksize=8192, rest=None)

  以二进制传输模式下载文件。cmd 应为恰当的 `RETR` 命令：`'RETR 文件名'`。callback 函数会在收到每个数据块时调用，传入的参数是表示数据块的一个字节。为执行实际传输，创建了底层套接字对象，可选参数 blocksize 指定了读取该对象时的最大块大小（这也是传入 callback 的数据块的最大大小）。已经选择了合理的默认值。rest 的含义与 `transfercmd()` 方法中的含义相同。

`FTP.``retrlines`(cmd, callback=None)

  Retrieve a file or directory listing in ASCII transfer mode. cmd should be an appropriate `RETR` command (see `retrbinary()`) or a command such as `LIST` or `NLST` (usually just the string `'LIST'`). `LIST` retrieves a list of files and information about those files. `NLST` retrieves a list of file names. The callback function is called for each line with a string argument containing the line with the trailing CRLF stripped. The default callback prints the line to `sys.stdout`.

`FTP.``set_pasv`(val)

  如果 val 为 true，则打开“被动”模式，否则禁用被动模式。默认下被动模式是打开的。

`FTP.``storbinary`(cmd, fp, blocksize=8192, callback=None, rest=None)

  以二进制传输模式存储文件。 cmd 应为恰当的 `STOR` 命令: `"STOR filename"`。fp 是一个 文件对象 (以二进制模式打开)，将使用它的 `read()` 方法读取它，用于提供要存储的数据，直到遇到 EOF，读取时的块大小为 blocksize。 参数 blocksize 的默认值为 8192。 可选参数 callback 是单参数函数，在每个数据块发送后都会用该数据块调用它。rest 的含义与 `transfercmd()` 方法中的含义相同。

  在 3.2 版更改: 添加了 rest 参数。

`FTP.``storlines`(cmd, fp, callback=None)

  Store a file in ASCII transfer mode. cmd should be an appropriate `STOR` command (see `storbinary()`). Lines are read until EOF from the file object fp (opened in binary mode) using its `readline()` method to provide the data to be stored. callback is an optional single parameter callable that is called on each line after it is sent.

`FTP.``transfercmd`(cmd, rest=None)

  在 FTP 数据连接上开始传输数据。如果传输处于活动状态，传输命令由 cmd 指定，需发送 `EPRT` 或 `PORT` 命令，然后接受连接 (accept)。如果服务器是被动服务器，需发送 `EPSV` 或 `PASV` 命令，连接到服务器 (connect)，然后启动传输命令。两种方式都将返回用于连接的套接字。

  If optional rest is given, a `REST` command is sent to the server, passing rest as an argument. rest is usually a byte offset into the requested file, telling the server to restart sending the file’s bytes at the requested offset, skipping over the initial bytes. Note however that RFC 959 requires only that rest be a string containing characters in the printable range from ASCII code 33 to ASCII code 126. The `transfercmd()` method, therefore, converts rest to a string, but no check is performed on the string’s contents. If the server does not recognize the `REST` command, an `error_reply` exception will be raised. If this happens, simply call `transfercmd()` without a rest argument.

`FTP.``ntransfercmd`(cmd, rest=None)

  类似于 `transfercmd()`，但返回一个元组，包括数据连接和数据的预计大小。如果预计大小无法计算，则返回的预计大小为 `None`。cmd 和 rest 的含义与 `transfercmd()` 中的相同。

`FTP.``mlsd`(path="", facts=[])

  使用 `MLSD` 命令以标准格式列出目录内容 (RFC 3659)。如果省略 path 则使用当前目录。facts 是字符串列表，表示所需的信息类型（如 `["type", "size", "perm"]`）。返回一个生成器对象，每个在 path 中找到的文件都将在该对象中生成两个元素的元组。第一个元素是文件名，第二个元素是该文件的 facts 的字典。该字典的内容受 facts 参数限制，但不能保证服务器会返回所有请求的 facts。

  3.3 新版功能.

`FTP.``nlst`(argument[, ...])

  返回一个文件名列表，文件名由 `NLST` 命令返回。可选参数 argument 是待列出的目录（默认为当前服务器目录）。可以使用多个参数，将非标准选项传递给 `NLST` 命令。

  注解

  如果目标服务器支持相关命令，那么 `mlsd()` 提供的 API 更好。

`FTP.``dir`(argument[, ...])

  生成目录列表，即 `LIST` 命令所返回的结果，并将其打印到标准输出。可选参数 argument 是待列出的目录（默认为当前服务器目录）。可以使用多个参数，将非标准选项传递给 `LIST` 命令。如果最后一个参数是一个函数，它将被用作 callback 函数，与 `retrlines()` 中的相同，默认将打印到 `sys.stdout`。本方法返回 `None`。

  注解

  如果目标服务器支持相关命令，那么 `mlsd()` 提供的 API 更好。

`FTP.``rename`(fromname, toname)

  将服务器上的文件 fromname 重命名为 toname。

`FTP.``delete`(filename)

  将服务器上名为 filename 的文件删除。如果删除成功，返回响应文本，如果删除失败，在权限错误时引发 `error_perm`，在其他错误时引发 `error_reply`。

`FTP.``cwd`(pathname)

  设置服务器端的当前目录。

`FTP.``mkd`(pathname)

  在服务器上创建一个新目录。

`FTP.``pwd`()

  返回服务器上当前目录的路径。

`FTP.``rmd`(dirname)

  将服务器上名为 dirname 的目录删除。

`FTP.``size`(filename)

  请求服务器上名为 filename 的文件大小。成功后以整数返回文件大小，未成功则返回 `None`。注意，`SIZE` 不是标准命令，但通常许多服务器的实现都支持该命令。

`FTP.``quit`()

  向服务器发送 `QUIT` 命令并关闭连接。 这是关闭一个连接的“礼貌”方式，但是如果服务器对 `QUIT` 命令的响应带有错误消息则这会引发一个异常。 这意味着对 `close()` 方法的调用，它将使得 `FTP` 实例对后继调用无效（见下文）。

`FTP.``close`()

  单方面关闭连接。 这不该被应用于已经关闭的连接，例如成功调用 `quit()` 之后的连接。 在此调用之后 `FTP` 实例不应被继续使用（在调用 `close()` 或 `quit()` 之后你不能通过再次发起调用 `login()` 方法重新打开连接）。

## 21.13.2. FTP_TLS 对象

`FTP_TLS` 类继承自 `FTP`，它定义了下述其他对象：

`FTP_TLS.``ssl_version`

  欲采用的 SSL 版本（默认为 `ssl.PROTOCOL_SSLv23`）。

`FTP_TLS.``auth`()

  通过使用 TLS 或 SSL 来设置一个安全控制连接，具体取决于 `ssl_version` 属性是如何设置的。

  在 3.4 版更改: 此方法现在支持使用 `ssl.SSLContext.check_hostname` 和 服务器名称指示 (参见 `ssl.HAS_SNI`) 进行主机名检查。

`FTP_TLS.``ccc`()

  将控制通道回复为纯文本。 这适用于发挥知道如何使用非安全 FTP 处理 NAT 而无需打开固定端口的防火墙的优势。

  3.3 新版功能.

`FTP_TLS.``prot_p`()

  设置加密数据连接。

`FTP_TLS.``prot_c`()

  设置明文数据连接。