# `ftplib` --- FTP 协议客户端

源代码： Lib/ftplib.py

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

默认编码为 UTF-8，遵循 RFC 2640。

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

    >>> from ftplib import FTP
    >>> ftp = FTP('ftp.us.debian.org')  # connect to host, default port
    >>> ftp.login()                     # user anonymous, passwd anonymous@
    '230 Login successful.'
    >>> ftp.cwd('debian')               # change into "debian" directory
    '250 Directory successfully changed.'
    >>> 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.'
    >>> with open('README', 'wb') as fp:
    >>>     ftp.retrbinary('RETR README', fp.write)
    '226 Transfer complete.'
    >>> ftp.quit()
    '221 Goodbye.'

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

class `ftplib.``FTP`(host='', user='', passwd='', acct='', timeout=None, source_address=None, *, encoding='utf-8')

  返回一个 `FTP` 类的新实例。当传入 host 时，将调用 `connect(host)` 方法。当传入 user 时，将额外调用 `login(user, passwd, acct)` 方法（其中 passwd 和 acct 若没有传入则默认为空字符串）。可选参数 timeout 指定阻塞操作（如连接尝试）的超时（以秒为单位，如果未指定超时，将使用全局默认超时设置）。source_address 是一个 2 元组 `(host, port)`，套接字在连接前绑定它，作为其源地址。encoding 参数指定目录和文件名的编码。

  `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 参数。

  3.9 版更變: 如果 timeout 参数设置为 0，创建非阻塞套接字时，它将引发 `ValueError` 来阻止该操作。添加了 encoding 参数，且为了遵循 RFC 2640，该参数默认值从 Latin-1 改为了 UTF-8。

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

  一个 `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 证书。

  3.9 版更變: 如果 timeout 参数设置为 0，创建非阻塞套接字时，它将引发 `ValueError` 来阻止该操作。添加了 encoding 参数，且为了遵循 RFC 2640，该参数默认值从 Latin-1 改为了 UTF-8。

  以下是使用 `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`

  所有异常的集合（一个元组），由于 FTP 连接出现问题（并非调用者的编码错误），`FTP` 实例的方法可能会引发这些异常。该集合包括上面列出的四个异常以及 `OSError` 和 `EOFError`。

也參考

`netrc` 模块

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

## 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)`，套接字在连接前绑定它，作为其源地址。

  引发一个 审计事件 `ftplib.connect` 并附带参数 `self`, `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)

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

  引发一个 审计事件 `ftplib.sendcmd` 并附带参数 `self`, `cmd`。

`FTP.``voidcmd`(cmd)

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

  引发一个 审计事件 `ftplib.sendcmd` 并附带参数 `self`, `cmd`。

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

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

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

  按照初始化时的 encoding 参数指定的编码，获取文件或目录列表。cmd 应是恰当的 `RETR` 命令（参阅 `retrbinary()`），也可以是诸如 `LIST` 或 `NLST` 之类的命令（通常就只是字符串 `'LIST'`）。`LIST` 获取文件列表以及那些文件的信息。`NLST` 获取文件名称列表。callback 函数会在每一行都调用，参数就是包含一行的字符串，删除了尾部的 CRLF。默认的 callback 会把行打印到 `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)

  以文本行模式存储文件。cmd 应为恰当的 `STOR` 命令 (请参阅 `storbinary()`)。 fp 是一个 文件对象 (以二进制模式打开)，将使用它的 `readline()` 方法读取它的每一行，用于提供要存储的数据，直到遇到 EOF。 可选参数 callback 是单参数函数，在每行发送后都会以该行作为参数来调用它。

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

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

  如果传入了可选参数 rest，则一条 `REST` 命令会被发送到服务器，并以 rest 作为参数。rest 通常表示请求文件中的字节偏移量，它告诉服务器重新开始发送文件的字节，从请求的偏移量处开始，跳过起始字节。但是请注意，`transfercmd()` 方法会将 rest 转换为字符串，但是不检查字符串的内容，转换用的编码是在初始化时指定的 encoding 参数。如果服务器无法识别 `REST` 命令，将引发 `error_reply` 异常。如果发生这种情况，只需不带 rest 参数调用 `transfercmd()`。

`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()` 方法重新打开连接）。

## 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`()

  设置明文数据连接。