gpt4 book ai didi

python-3.x - python3的编码问题并单击包

转载 作者:行者123 更新时间:2023-12-03 08:08:26 25 4
gpt4 key购买 nike

当lib click 检测到运行时是 python3 但编码是 ASCII 然后它突然结束 python 程序:

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 http://click.pocoo.org/python3/ for mitigation steps.

我在我的案例中找到了这个问题的原因,当我从我的 Mac 连接到我的 Linux 主机时,Terminal.app 将 SSH session 区域设置设置为我的 Mac 区域设置 (es_ES.UTF-8) 但是我的 Linux 主机尚未安装这样的语言环境(仅 en_US.utf-8)。

我应用了一个初步的解决方法来修复它(但它有很多问题,请参阅已接受的答案):

import locale, codecs
# locale.getpreferredencoding() == 'ANSI_X3.4-1968'
if codecs.lookup(locale.getpreferredencoding()).name == 'ascii':
os.environ['LANG'] = 'en_US.utf-8'

编辑:要获得更好的补丁,请参阅我接受的答案。

我所有的 linux 主机都安装了“en_US.utf-8”作为语言环境(Fedora 默认使用它)。

我的问题是: 有没有更好(更健壮)的方法来选择/强制在 python3 脚本中使用语言环境? 例如,设置系统中可用的语言环境之一。

也许有一种不同的方法可以解决这个问题,但我没有找到。

最佳答案

嗯,我最初的解决方法有很多缺陷,我必须通过关于编码的 click 库检查,但是编码本身没有固定,所以当输入参数或输出有非 ascii 字符时我会得到异常。

我必须实现一个更复杂的方法,包括 3 个步骤:设置语言环境,在 std 输入/输出中正确编码并重新编码命令行参数,此外,如果第一次尝试设置语言环境,我已经添加了一个“友好”退出没有按预期工作:

def prevent_ascii_env():
"""
To avoid issues reading unicode chars from stdin or writing to stdout, we need to ensure that the
python3 runtime is correctly configured, if not, we try to force to utf-8,
but It isn't possible then we exit with a more friendly message that the original one.
"""
import locale, codecs, os, sys
# locale.getpreferredencoding() == 'ANSI_X3.4-1968'
if codecs.lookup(locale.getpreferredencoding()).name == 'ascii':
os.environ['LANG'] = 'en_US.utf-8'
if codecs.lookup(locale.getpreferredencoding()).name == 'ascii':
print("The current locale is not correctly configured in your system")
print("Please set the LANG env variable to the proper value before to call this script")
sys.exit(-1)
#Once we have the proper locale.getpreferredencoding() We can change current stdin/out streams
_, encoding = locale.getdefaultlocale()
import io
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding=encoding, errors="replace", line_buffering=True)
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding=encoding, errors="replace", line_buffering=True)
sys.stdin = io.TextIOWrapper(sys.stdin.detach(), encoding=encoding, errors="replace", line_buffering=True)
# And finally we need to re-encode the input parameters
for i, p in enumerate(sys.argv):
sys.argv[i] = os.fsencode(p).decode()

这个补丁解决了几乎所有的问题,但是它有一个警告,方法 shutils.get_terminal_size() 引发了 ValueError 因为 sys.__stdout__ 已经分离, click lib 使用该方法打印帮助,要修复它我不得不应用 lib67x104

def wrapper_get_terminal_size():
"""
Replace the original function termui.get_terminal_size (click lib) by a new one
that uses a fallback if ValueError exception has been raised
"""
from click import termui, formatting

old_get_term_size = termui.get_terminal_size
def _wrapped_get_terminal_size():
try:
return old_get_term_size()
except ValueError:
import os
sz = os.get_terminal_size()
return sz.columns, sz.lines
termui.get_terminal_size = _wrapped_get_terminal_size
formatting.get_terminal_size = _wrapped_get_terminal_size

通过这些更改,当环境配置了错误的语言环境但系统支持 en_US.utf-8(这是 Fedora 默认语言环境)时,我的所有脚本现在都可以正常工作。

如果您发现此方法有任何问题或有更好的解决方案,请添加新答案。

EDIT :有一个 Unresolved 问题(增强), http://bugs.python.org/issue15216 ,它将允许轻松更改创建(未使用)流中的编码(sys.std *)。但是针对python 3.7所以,我们还得等一会儿。

EDIT (2017-12-08):我看到py3.7有一个PEP 538,它会在启动过程中改变python3编码管理的整个行为,我认为新的方法会解决原来的问题: https://www.python.org/dev/peps/pep-0538/

恕我直言,针对python 3.7的编码问题的更改应该在几年前就计划好了,但我猜迟到总比没有好。

关于python-3.x - python3的编码问题并单击包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32234393/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com