在latin1编码的文件中写入和读取字符串

8

这里有2个代码示例,Python3:第一个示例使用latin1编码写入两个文件:

s='On écrit ça dans un fichier.'
with open('spam1.txt', 'w',encoding='ISO-8859-1') as f:
    print(s, file=f)
with open('spam2.txt', 'w',encoding='ISO-8859-1') as f:
    f.write(s)

第二个使用相同的编码读取相同的文件:
with open('spam1.txt', 'r',encoding='ISO-8859-1') as f:
    s1=f.read()
with open('spam2.txt', 'r',encoding='ISO-8859-1') as f:
    s2=f.read()

现在,打印 s1 和 s2 我会得到:
On écrit ça dans un fichier.

替代最初的“On écrit ça dans un fichier。”

有什么问题吗?我也尝试使用io.open,但我错过了一些东西。有趣的是,我在Python2.7中没有这样的问题,因为它具有现在已经消失的str.decode方法...

能有人帮帮我吗?


你是否百分之百确定这些文件是用Latin-1编码写的?看起来非常像UTF-8数据。 - Martijn Pieters
2
>>> 'On écrit ça dans un fichier.'.encode('utf8').decode('latin1') 的输出结果为 'On écrit ça dans un fichier.' - Martijn Pieters
1个回答

8

您的数据已以UTF-8编码写出:

>>> 'On écrit ça dans un fichier.'.encode('utf8').decode('latin1')
'On écrit ça dans un fichier.'

这意味着你没有编写Latin-1数据,或者你的源代码保存为UTF-8,但你声明了你的脚本(使用PEP 263兼容头)是Latin-1格式。

如果你使用下面这样的头来保存Python脚本:

# -*- coding: latin-1 -*-

如果你的文本编辑器使用UTF-8编码保存文件,那么字符串字面值:

s='On écrit ça dans un fichier.'

如果用相同的方式,Python也会误解这个值。将结果unicode值保存为Latin-1格式,然后再以Latin-1格式读取,可以保留错误。

要进行调试,请仔细查看第一个脚本中的print(s.encode('unicode_escape'))。如果它看起来像:

b'On \\xc3\\xa9crit \\xc3\\xa7a dans un fichier.'

如果您的源代码编码和PEP-263头文件不一致,那么源代码应该如何解释就会产生分歧。如果您的源代码正确解码,则输出结果应为:

b'On \\xe9crit \\xe7a dans un fichier.'

如果Spyder在任何情况下都无视PEP-263头文件并将源代码读取为Latin-1编码,建议避免使用非ASCII字符,而是使用转义码,可以使用\uxxxx的unicode编码点。
s = 'On \u00e9crit \u007aa dans un fichier.'

或使用一字节转义代码\xaa来表示其编码点小于256的字符:

s = 'On \xe9crit \x7aa dans un fichier.'

你的编辑器将源代码保存为Latin1格式。 - Martijn Pieters
这是因为 s 本身就是不正确的。这不是你的发行版的问题,而是你的源代码保存方式的问题。 - Martijn Pieters
文件的第一个十六进制是:23 20 2D...,对应于 # - 因此,该文件的编码应为 ANSI 或 CP1252但是使用头部 # -*- coding: cp1252 -*- 也没有改变...并且我要强调的是,该字符串通过 print(s) 在编辑器或控制台中正确地显示。 - François Coulombeau
@Coulombeau: 很有趣!看起来Spyder忽略了PEP 263头文件。在创建文字时,您可以改用\uxxxx转义字符。 - Martijn Pieters
当脚本从IDLE运行时,print(s.encode('unicode_escape'))是正确的,但当从Spyder运行时则是错误的。 - François Coulombeau
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接