为什么 Python3 在 UTF-8 上会中断,而 Python2 却不会,其他条件都相同?

问题描述 投票:0回答:1

我有一个以 centos7 作为基础镜像的 Docker 容器,并且

python --version
=
Python 2.7.5
python3 --version
=
Python 3.6.8

我的 ENTRYPOINT 是一个短的

run.sh
文件。

#!/bin/bash
locale >> locale.txt
python3 /home/scripts/script.py >> output.txt
while :
do
    sleep 10000
done

script.py
是:

#!/bin/python
path_to_file = '/home/file.json'
print('starting')
try:
    with open(path_to_file, "r") as file:
        data = file.read()
        print(data)
except Exception as e: print(e)
print('ending')

最后,

/home/file.json
仅包含:

"°"

启动容器并使用

docker exec -it container-name bash
输入后,我检查
output.txt
,其内容为:

starting
'ascii' codec can't decode byte 0xc2 in position 1: ordinal not in range(128)
ending

python3
中的
python
更改为
run.sh
并重做该过程会导致
output.txt
具有:

starting
"°"
ending

在这两种情况下,locale.txt 都有:

LANG=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

但是,在 Docker 容器的 bash 会话中在我的终端中运行

locale
会给出:

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

在 bash 会话中运行

python3 script.py
给我:

starting
"°"
ending

我在文档中发现,如果系统没有配置字符集,Python 2 会从系统配置中读取并使用 ASCII。当

encoding
参数未提供给
open
函数时,Python 3 的行为方式似乎相同。我一定是误解了文档?

Python 2 和 Python 3 之间的区别是什么导致在 Docker 容器的 ENTRYPOINT 脚本中运行时 Python 2 成功而 Python 3 失败?

python docker utf-8
1个回答
0
投票

Python 2 根本不尝试处理编码。它天真地逐字节读取。

相比之下,Python 3 区分以二进制模式打开的文件(逐字节读取,并返回

bytes

 对象)和文本模式(尝试使用编码,如果文件包含以下序列则失败)在该编码中无效,如果成功则返回 
str
)。

您尚未识别文件的编码;如果它是有效的 UTF-8 文件(这是我通常推荐的),请使用

encoding="utf-8"

。在 Windows 上,您可能需要不同的编码;但当然,您需要了解字符编码,并指定正确的编码。

要强制Python 3使用特定编码,而不更改源文件,可以将环境变量

PYTHONIOENCODING

设置为合适的值;例如

export PYTHONIOENCODING="utf-8"
另请参阅 

https://nedbatchelder.com/text/unipain.html 和 Joel Spolsky 的 每个软件开发人员绝对必须了解 Unicode 和字符集(没有例外!)

如果您需要帮助识别文本文件的编码,请尝试

https://tripleee.github.io/8bit/(全面披露:我是此页面的作者)配备十六进制转储或 Python 3 的 repr

 文件中的字节数(...尽管这对于 UTF-8 没有帮助,所以也许可以先尝试一下)。

© www.soinside.com 2019 - 2024. All rights reserved.