Python 为什么struct.unpack()在字符串长度正确时引发异常?

Python 为什么struct.unpack()在字符串长度正确时引发异常?,python,struct,Python,Struct,我有一个文件,其中有些行是可以忽略的元数据,有些行是struct.pack调用的打印结果。假设f.txt是: key: 3175 \x00\x00\x00\x00\x00\x00\x00\x00 key: 3266 \x00\x00\x00\x00\x00\x00\x00\x00 在本例中,以“key”开头的行是元数据,字节字符串是我要提取的值。同样在本例中,两字节字符串行是使用struct.pack('d',0)生成的。以下代码是我要执行的操作: import struct for line

我有一个文件,其中有些行是可以忽略的元数据,有些行是struct.pack调用的打印结果。假设f.txt是:

key: 3175
\x00\x00\x00\x00\x00\x00\x00\x00
key: 3266
\x00\x00\x00\x00\x00\x00\x00\x00
在本例中,以“key”开头的行是元数据,字节字符串是我要提取的值。同样在本例中,两字节字符串行是使用struct.pack('d',0)生成的。以下代码是我要执行的操作:

import struct
for line in open('f.txt', 'r'):      
  # if not metadata, remove newline character and unpack
  if line[0:3] != 'key':
    val = struct.unpack('d', line[0:-1])
    appendToList(val) # do something else with val
这样,我得到:“struct.error:unpack需要长度为8的字符串参数”

如果我们稍微修改代码:

import struct
for line in open('f.txt', 'r'):      
  # if not metadata, remove newline character and unpack
  if line[0:3] != 'key': print line[:-1]
然后输出如预期的那样:

\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00
如果我将字节字符串直接放入解包调用,那么我成功了:

import struct
# successful unpacking
struct.unpack('d', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
我已尝试通过以下不同的线路进行解包,所有这些线路都给出了相同的结果:

str(line)
repr(line)
b"%s" % line

对于txt文件中的字符串:

\x00\x00\x00\x00\x00\x00\x00\x00
在python中,它实际上是:

\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
所以你应该解析这个字符串并转换它。对于您的示例,使用以下代码可以得到您想要的:

s = line.strip().split('\\x')
r = ''
for v in s:
    if len(v) > 0:
        print v
        r += struct.pack('b', int(v, 16))
val = struct.unpack('d', r)[0]
print val

对于txt文件中的字符串:

\x00\x00\x00\x00\x00\x00\x00\x00
在python中,它实际上是:

\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00
所以你应该解析这个字符串并转换它。对于您的示例,使用以下代码可以得到您想要的:

s = line.strip().split('\\x')
r = ''
for v in s:
    if len(v) > 0:
        print v
        r += struct.pack('b', int(v, 16))
val = struct.unpack('d', r)[0]
print val

文本文件中的实际字节是在python控制台上看到的字符串转义字节,而不是它们所表示的二进制字节

例如,文本文件包含
\x00
(四个字节长),而不是空字节(一个字节长)

在struct处理该文本之前,您需要取消对其进行scape(将其转换为二进制形式)

(请注意,您的文件格式不是很好,因为您可能会有一行以“key:”开头的数字!例如,
“key:\x00\x00\x00”
是一个有效的数字
6.8388560679e-313
!如果您每隔一行交替使用元数据和值,您应该只跟踪您所在的行号并解析ac。))

这里有一个比其他解决方案简单得多的解决方案

Python有一个名为的内置编解码器,它将Python转义码转换为它们表示的二进制字节:

for line in thefile:
    if line[0:3] != 'key':
        binaryline = line[:-1].decode('string_escape')
        val = struct.unpack('d', binaryline)

如果你有一个大的这些双值列表,并希望将它们有效地存储在一个数组结构中,请考虑使用模块而不是<代码>结构> <代码>:

vals = array.array('d')

for line in thefile:
    if line[0:3] != 'key':
        binaryline = line[:-1].decode('string_escape')
        # appends binaryline to vals array, interpreting as a double
        vals.fromstring(binaryline)

文本文件中的实际字节是在python控制台上看到的字符串转义字节,而不是它们所表示的二进制字节

例如,文本文件包含
\x00
(四个字节长),而不是空字节(一个字节长)

在struct处理该文本之前,您需要取消对其进行scape(将其转换为二进制形式)

(请注意,您的文件格式不是很好,因为您可能会有一行以“key:”开头的数字!例如,
“key:\x00\x00\x00”
是一个有效的数字
6.8388560679e-313
!如果您每隔一行交替使用元数据和值,您应该只跟踪您所在的行号并解析ac。))

这里有一个比其他解决方案简单得多的解决方案

Python有一个名为的内置编解码器,它将Python转义码转换为它们表示的二进制字节:

for line in thefile:
    if line[0:3] != 'key':
        binaryline = line[:-1].decode('string_escape')
        val = struct.unpack('d', binaryline)

如果你有一个大的这些双值列表,并希望将它们有效地存储在一个数组结构中,请考虑使用模块而不是<代码>结构> <代码>:

vals = array.array('d')

for line in thefile:
    if line[0:3] != 'key':
        binaryline = line[:-1].decode('string_escape')
        # appends binaryline to vals array, interpreting as a double
        vals.fromstring(binaryline)

您确定错误没有发生在文件的最后一行,这可能是缺少换行符吗?第一次调用解包失败,因此情况并非如此。您确定错误没有发生在文件的最后一行,这可能是缺少换行符吗?第一次调用解包失败,因此情况并非如此。D在不添加字符串时,
“”。加入它们。字符串是不可变的,因此重复添加它们非常慢。@arbenson,既然您显然不关心性能,为什么不将浮点的
repr()
写入文件,并用
float()读回它们呢
不要添加字符串,
''。加入它们。字符串是不可变的,因此重复添加它们非常慢。@arbenson,既然你显然不关心性能,为什么不将浮点的
repr()
写入文件,并用
float()读回它们呢