Python 3 支持 — 单击文档
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.stdin
、sys.stdout
、sys.stderr
以二进制方式打开,但在某些情况下它们支持Unicode输出。 Click 试图不破坏这一点,但提供了对强制流基于 Unicode 的支持。sys.argv
总是基于字节的。 Click 会将字节传递给所有输入类型并根据需要进行转换。 STRING 类型会通过尝试最合适的编码自动将输入值正确解码为字符串。- 在处理文件时,Click 永远不会通过 Unicode API,而是使用操作系统的字节 API 打开文件。
在 Python 3 中,以下是正确的:
sys.stdin
、sys.stdout
和sys.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 认为您仅限于 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 错误跟踪器中的讨论:
- ASCII 是一种糟糕的文件系统默认编码
- 使用 surrogateescape 作为默认错误处理程序
- Python 3 在 C 语言环境中引发 Unicode 错误
- LC_CTYPE=C:pydoc 使终端处于不可用状态(这与 Click 相关,因为分页器支持由 stdlib pydoc 模块提供)
注意(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