Python 在读取或写入文件时是否始终使用 UTF-8?(仅使用文件和模式参数打开函数。

Does Python always use UTF-8 when reading from or writing to a file? (Open function with only file and mode args.)

提问人:Watchduck 提问时间:9/19/2023 最后编辑:Watchduck 更新时间:9/19/2023 访问量:101

问:

我的印象是,读取和写入文件总是使用 UTF-8。
我试图通过对脚本使用不同的编码来找到一个反例,但没有找到。

我的示例使用 Yen-Symbol,其 UTF-8 编码为 。C2 A5
'¥'.encode('utf-8') == b'\xc2\xa5'

假设文件yen.txt,其中包含两个字节。
在哪些情况下,以下代码可能会失败?
C2 A5

with open('yen.txt', 'r') as f:
    assert f.read() == '¥'

或者下面的代码可以生成一个不包含字节的文本文件吗?C2 A5

with open('yen.txt', 'w') as f:
    f.write('¥')

我所说的“情况”是指脚本的编码或操作系统的某些设置。

假设脚本使用某种编码,允许 Yen-Symbol。
(否则,它相当于一个问号。

我尝试了 编写脚本,结果是一样的。
我想知道,文本文件是否可能只包含字节,
因为这是 CP 437 中日元符号的码位。
# coding: cp4379D
'¥'.encode('cp437') == b'\x9d'

顺便说一句,我在 GitHub 上上传了修改后的脚本,不知何故日元符号消失了。
有人知道为什么吗?

python utf-8 字符编码

评论

0赞 Barmar 9/19/2023
可以使用参数 to 指定编码。它默认为 UTF-8。encodingopen()
2赞 JimChr - R4GN4R 9/19/2023
一般来说,我更喜欢这样打开:而不是特别是在处理未知数据时。因为如果以编码打开文件,则可能无法打开它,因为无法以utf-8格式解码的特殊字符open('yen.txt', 'rb')open('yen.txt', 'r')utf-8
0赞 flakes 9/19/2023
“不知何故,日元符号消失了” 如果你看一下原始文件,你可以看到它在那里,但前端只是不知道如何解析它:raw.githubusercontent.com/entenschule/examples_py/main/......
4赞 Mark Tolonen 9/19/2023
始终为文本模式显式指定编码。它并不总是默认为 UTF-8。请参阅文档。仅供参考@Barmar
0赞 Watchduck 9/19/2023
文档说,它使用 .对我来说,这是行不通的。() 但有效,并返回“UTF-8”。locale.getencoding()AttributeError: module 'locale' has no attribute 'getencoding'locale.getpreferredencoding()

答:

-1赞 Watchduck 9/19/2023 #1

正如 Mark Tolonen 所指出的,编码实际上并没有默认值。

在函数的注释中,它声明如下:open

在文本模式下,如果未指定编码,则使用的编码为 platform dependent:被调用以获取 当前区域设置编码。
(对于读取和写入原始字节,请使用二进制 模式,并保留未指定编码。
locale.getpreferredencoding(False)

在 Linux 和 Mac 上,首选编码可能是 ,在 Windows 上可能是 。'UTF-8''cp1252'

>>> import locale
>>> locale.getpreferredencoding(True)
'UTF-8'

评论

0赞 Joachim Sauer 9/19/2023
你确定最后一句话吗?平台默认编码是 UTF-8 几乎是所有现代类 unix 操作系统(包括 Linux、Mac OS X 和 Android),但在 Windows 中,它通常是不同的编码(具体不知道 Python,但 Java 面临同样的问题)。这个答案看起来像是“它在我的机器上工作”的经典案例。
0赞 Watchduck 9/19/2023
你是对的。在 Windows 上,它是 .Windows-1252 (所以我想在 Windows 上,如果没有指定编码,“¥”应该保存为 A5。'cp1252'
0赞 Joachim Sauer 9/19/2023
甚至这个答案也是不完整的。在 Windows 上,这取决于配置的区域设置。理智的做法是不要对该函数的返回值进行任何假设。如果需要 UTF-8,请指定它。如果需要平台默认编码,请显式获取该编码(或者不提供编码并默认使用它)。