Python 3 支持 — 单击文档

来自菜鸟教程
Click/docs/7.x/python3
跳转至:导航、​搜索

Python 3 支持

Click 支持 Python 3,但与所有其他命令行实用程序库一样,它受到 Python 3 中的 Unicode 文本模型的影响。 文档中的所有示例都经过编写,以便它们可以在 Python 2.x 和 Python 3.4 或更高版本上运行。

Python 3 限制

目前,Click 在 Python 3 中存在一些问题:

  • Unix 中的命令行传统上以字节为单位,而不是 Unicode。 虽然所有这些都有编码提示,但通常在某些情况下可能会中断。 最常见的一种是与具有不同语言环境的机器的 SSH 连接。

    由于缺乏对往返代理转义的支持,错误配置的环境目前可能导致 Python 3 中的各种 Unicode 问题。 这不会在 Click 本身中修复!

    有关更多信息,请参阅 Python 3 代理处理

  • 默认情况下,Python 3 中的标准输入和输出以 Unicode 模式打开。 在某些情况下,单击必须以二进制模式重新打开流。 因为没有标准化的方法来做到这一点,这可能并不总是有效。 在测试命令行应用程序时,这主要会成为一个问题。

    这不受支持:

    sys.stdin = io.StringIO('Input here')
    sys.stdout = io.StringIO()

    相反,您需要这样做:

    input = 'Input here'
    in_stream = io.BytesIO(input.encode('utf-8'))
    sys.stdin = io.TextIOWrapper(in_stream, encoding='utf-8')
    out_stream = io.BytesIO()
    sys.stdout = io.TextIOWrapper(out_stream, encoding='utf-8')

    请记住,在这种情况下,如果要访问缓冲区内容,则需要使用 out_stream.getvalue() 而不是 sys.stdout.getvalue(),因为包装器不会转发该方法。


Python 2 和 3 的差异

Click 尝试通过遵循两种语言的最佳实践来最小化 Python 2 和 Python 3 之间的差异。

在 Python 2 中,以下是正确的:

  • sys.stdinsys.stdoutsys.stderr以二进制方式打开,但在某些情况下它们支持Unicode输出。 Click 试图不破坏这一点,但提供了对强制流基于 Unicode 的支持。
  • sys.argv 总是基于字节的。 Click 会将字节传递给所有输入类型并根据需要进行转换。 STRING 类型会通过尝试最合适的编码自动将输入值正确解码为字符串。
  • 在处理文件时,Click 永远不会通过 Unicode API,而是使用操作系统的字节 API 打开文件。

在 Python 3 中,以下是正确的:

  • sys.stdinsys.stdoutsys.stderr 默认是基于文本的。 当 Click 需要一个二进制流时,它会尝试发现底层的二进制流。 请参阅 Python 3 限制 了解其工作原理。

  • sys.argv 始终基于 Unicode。 这也意味着 Click 中类型的输入值的本机类型是 Unicode,而不是字节。

    如果终端设置不正确并且 Python 无法确定编码,这会导致问题。 在这种情况下,Unicode 字符串将包含编码为代理转义的错误字节。

  • 在处理文件时,Click 将始终通过使用操作系统报告或猜测的文件系统编码来使用 Unicode 文件系统 API 调用。 文件名支持代理,因此即使环境配置错误,也应该可以通过 File 类型打开文件。


Python 3 代理处理

Python 3 中的 Click 执行标准库中的所有 Unicode 处理并受其行为的约束。 在 Python 2 中,Click 自己完成所有 Unicode 处理,这意味着错误行为存在差异。

最明显的区别是在 Python 2 中,Unicode 将“正常工作”,而在 Python 3 中,它需要格外小心。 这样做的原因是在 Python 3 中,编码检测是在解释器中完成的,而在 Linux 和某些其他操作系统上,其编码处理是有问题的。

最大的挫折来源是初始化系统(sysvinit、upstart、systemd 等)、部署工具(salt、puppet)或 cron 作业(cron)调用的 Click 脚本将拒绝工作,除非导出 Unicode 语言环境。

如果 Click 遇到这样的环境,它将阻止进一步执行以强制您设置语言环境。 这样做是因为 Click 一旦被调用就无法知道系统的状态并在 Python 的 Unicode 处理开始之前恢复这些值。

如果你在 Python 3 中看到类似这样的错误:

Traceback (most recent call last):
  ...
RuntimeError: Click will abort further execution because Python 3 was
  configured to use ASCII as encoding for the environment. Either switch
  to Python 2 or consult the Python 3 section of the docs for
  mitigation steps.

笔记

在 Python 3.7 及更高版本中,由于 PEP 538PEP 540,在许多情况下您将不再获得 RuntimeError ],它改变了未配置环境中的默认假设。


您正在处理 Python 3 认为您仅限于 ASCII 数据的环境。 这些问题的解决方案取决于您的计算机运行的区域设置。

例如,如果您有一台德国 Linux 机器,您可以通过将语言环境导出到 de_DE.utf-8 来解决问题:

export LC_ALL=de_DE.utf-8
export LANG=de_DE.utf-8

如果您使用的是美国机器,则 en_US.utf-8 是首选编码。 在一些较新的 Linux 系统上,您还可以尝试将 C.UTF-8 作为语言环境:

export LC_ALL=C.UTF-8
export LANG=C.UTF-8

据报道,在某些系统上,UTF-8 必须写为 UTF8,反之亦然。 要查看支持哪些语言环境,您可以调用 locale -a

locale -a

您需要在调用 Python 脚本之前执行此操作。 如果您对此原因感到好奇,可以加入 Python 3 错误跟踪器中的讨论:

注意(Python 3.7 以上):即使您的语言环境可能没有正确配置,Python 3.7 Click 也不会引发上述异常,因为 Python 3.7 程序更擅长选择默认语言环境。 这不会改变您的语言环境可能配置错误的一般问题。


Unicode 文字

从 Click 5.0 开始,在 Python 2 中使用 unicode_literals 未来导入会有警告。 之所以这样做是因为此导入的负面后果是由于将 Unicode 数据引入无法处理它们的 API 而无意中导致错误。 有关此问题的一些示例,请参阅关于此 github 问题的讨论:python-future#22

如果您在定义 Click 命令或调用 click 命令的任何文件中使用 unicode_literals,您将收到警告。 强烈建议您不要使用 unicode_literals,而是为您的 Unicode 字符串使用显式的 u 前缀。

如果您确实想忽略警告并继续使用 unicode_literals,但您自己会承担风险,您可以按如下方式禁用警告:

import click
click.disable_unicode_literals_warning = True