【发布时间】:2017-10-20 00:13:23
【问题描述】:
我有一个使用 Python 2.7 在 Windows 机器 (Win 7) 上记录数据的脚本。我想使用 Python 3.5 在我的 RHEL 机器上读取这些文件。我不断收到以下错误(或类似错误):
UnicodeDecodeError:“ascii”编解码器无法解码位置 825929 中的字节 0xe6:序数不在范围内 (128)
更糟糕的是,数据以 hex/ascii 格式传入计算机(我不知道制造商为什么这样做),因此整数 27035 在文本文件中显示为 0x699b。所以数据看起来像这样:
0001100011000190001600011000110001300013000120001200013000140001a0002
两个在 Python 2.7 中写入数据我只是这样做:
with open('dst.txt', 'w') as fid:
fid.write(data_stream)
我在办公室电脑上使用 2.7 时阅读这些文件没有问题,但在切换到 3.5 后我就可以了。
这曾经在 2.7 下工作:
with open('src.txt', 'r') as tmp:
data = tmp.read().split('\n')
在3.5下使用相同的脚本导致错误(如上),所以我定义了编码:
with open('src.txt', 'r', encoding='latin-1') as tmp:
data = tmp.read().split('\n')
这在大多数情况下都有效(奇怪,因为 Python 2.7 下的“open”应该默认为 encoding='ascii'...注意:将编码定义为“ascii”仍然会导致错误),我至少可以阅读以这种方式归档。现在的问题是,并非所有行都包含相同数量的字符(它们应该!)。很少有一行缺少一两个字符。我通过以下方式找到较短的行:
for r in data:
if len(r) < 7721:
print(r)
在这些行中,我发现了奇怪的字符,例如:
Ö\221Á
Ö\231\231Ù
其中 \221 和 \231 显示为单个字符(即不是您所期望的四个)。
我想我的问题是:这里发生了什么?我可以丢弃没有足够字符的行(这将少于数据的 1%),但这让我很恼火,这不起作用。
这是否是由于数据首先转换为十六进制,然后写入 ascii 编码,然后通过 latin-1 解码造成的(发生了很多事情)。如果是这样,那我为什么不能通过指定ascii编码来解码数据呢?
编辑 我以不同的方式加载数据:
open('src.txt', 'rU', encoding='latin-1')
open('src.txt', 'rb')
open('src.txt', 'rU', encoding='Windows-1252')
数据保持不变,但误译部分发生了变化:
fÖ\211Áffe7700
f\xd6\x89\xc1ffe7700
fÖ‰Áffe7700
“f”和“ffe7700”之间的任何内容都不起作用。
【问题讨论】:
-
您的意思是该文件是二进制文件吗?在这种情况下,您希望在打开文件时通过
"rb"而不是"r"将其读取为字节。在 python2 中,我认为它不会改变任何东西,但在 python 3 中,它会将原始数据读取为bytes对象而不是str对象,这是因为在 python 3 中,所有字符串都是 unicode,这在处理时真的很痛苦原始字节数据。 -
不,它是一个文本文件,其中包含以十六进制写入的数据(这是否使它成为二进制?)。将读取设置为“rb”没有帮助,我的行仍然较短
-
当你说 "整数 27035 在文本文件中显示为 0x699b" 你的意思是文件的十六进制表示显示
0x699b还是你的意思是字符串"0x699b"是文件中的文本吗?然后是 “所以数据看起来像这样:” 之后的数据是文本编辑器或十六进制阅读器中显示的内容吗?这些数据与27035有什么关系? -
字符串是文件中的文本。我显示的数据是文本文件中显示的数据,与 27035 无关。我选择 27035 作为任意示例,而发布的文本来自实际的文本文件。在数据文件中,每个十六进制字符串的长度为 5 个字符,因此您可以通过将大长字符串分成五个字符段并使用 int 来转换为 int(例如 int(line[:5], 16)
-
好的,所以整数
27035实际上会显示为0699b,作为一长串十六进制数字的一部分,所以文件应该只包含数字、abcdef和换行符?所以你告诉我它包含在 2.7 中可以正常工作但在 3.5 中不能正常工作的奇数非 ascii 字符?我觉得有点难以置信,你确定只有在使用 python 3 时才会出现问题吗?
标签: python python-2.7 encoding python-3.5 python-2to3