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

   设置明文数据连接。
