在 Python 中解压缩格式字符

Unpack format characters in Python

提问人:Sir D 提问时间:2/7/2012 最后编辑:Peter MortensenSir D 更新时间:6/19/2017 访问量:4217

问:

我需要这个Perl字符串的Python模拟:

unpack("nNccH*", string_val)

我需要 Python 格式字符的 - 数据格式。nNccH*

在Perl中,它将二进制数据解压缩为五个变量:

  • “network”(big-endian)中的 16 位值
  • “network”(big-endian)中的 32 位值
  • 有符号字符(8 位整数)值
  • 有符号字符(8 位整数)值
  • 十六进制字符串,高半字节优先

但是我不能在Python中做到这一点

更多:

bstring = ''
while DataByte = client[0].recv(1):
    bstring += DataByte
print len(bstring)
if len(bstring):
    a, b, c, d, e = unpack("nNccH*", bstring)

我从来没有用Perl或Python写过,但我目前的任务是写一个用Perl写的多线程Python服务器......

python perl 解包

评论

0赞 Senthil Kumaran 2/7/2012
我可以找到除 H* 之外的所有东西的等价物,我假设你会玩 p 或 s。
0赞 pojo 2/7/2012
您将需要计算字符串大小,此答案可能会有所帮助。stackoverflow.com/a/5849224/70350
0赞 S.Lott 2/7/2012
"while DataByte = client[0].recv(1):"不是 Python。这永远行不通。
0赞 Eli Bendersky 2/7/2012
@SenthilKumaran:AFAIR的意思是“剩下的元素多少就剩多少”,所以他可以在之前把所有东西都拆开,然后把剩下的都拿起来而不拆包*H*
0赞 Eli Bendersky 2/7/2012
顺便说一句,D先生,感谢您编辑和澄清问题。不过,正如 S.Lott 所注意到的那样,最后一个代码片段意义不大

答:

7赞 Eli Bendersky 2/7/2012 #1

您要查找的等效 Python 函数是 。格式字符串的文档如下:http://docs.python.org/library/struct.htmlstruct.unpack

如果您真正解释您需要什么样的开箱,您将有更好的机会获得帮助。不是每个人都知道Perl。

评论

0赞 Sir D 2/7/2012
谢谢。我已经阅读了 perl 和 python 解包文档。但到目前为止,我不明白有些时刻。
0赞 Senthil Kumaran 2/7/2012
@Eli - 直接翻译可能会有小麻烦。例如,如何在 python 中执行 H*?我想,用户本可以更好地表达这个问题。
0赞 Eli Bendersky 2/7/2012
@SenthilKumaran:请注意,用户在我回答编辑了问题。在编辑之前,他没有在Perl中列出格式chars的含义
0赞 S.Lott 2/7/2012
@SirD:“到目前为止,我不明白有些时刻”。请具体说明您不理解的内容。请更新问题,说出您不理解的内容。
8赞 unutbu 2/7/2012 #2

Perl格式相当于Python格式。 在 Python 中没有 Perl 的直接等价物。"nNcc""!HLbb""H*"

有两个问题。

  • Python 不接受通配符,struct.unpack*
  • Python 不会“十六进制化”数据字符串struct.unpack

第一个问题可以使用类似 的辅助函数来解决。unpack

第二个问题可以通过以下方法解决:binascii.hexlify

import struct
import binascii

def unpack(fmt, data):
    """
    Return struct.unpack(fmt, data) with the optional single * in fmt replaced with
    the appropriate number, given the length of data.
    """
    # http://stackoverflow.com/a/7867892/190597
    try:
        return struct.unpack(fmt, data)
    except struct.error:
        flen = struct.calcsize(fmt.replace('*', ''))
        alen = len(data)
        idx = fmt.find('*')
        before_char = fmt[idx-1]
        n = (alen-flen)//struct.calcsize(before_char)+1
        fmt = ''.join((fmt[:idx-1], str(n), before_char, fmt[idx+1:]))
        return struct.unpack(fmt, data)

data = open('data').read()
x = list(unpack("!HLbbs*", data))
# x[-1].encode('hex') works in Python 2, but not in Python 3
x[-1] = binascii.hexlify(x[-1])
print(x)

当在此 Perl 脚本生成的数据上进行测试时:

$line = pack("nNccH*", 1, 2, 10, 4, '1fba');
print "$line";

Python 脚本产生

[1, 2, 10, 4, '1fba']

评论

0赞 Sven Marnach 2/7/2012
另一种选择是 。binascii.hexlify()str.encode("hex")
1赞 Mark Tolonen 2/7/2012
如果您想要 Python 3 兼容性,则需要在计算时,否则会产生“16.0”并破坏格式字符串。//nstr(n)
0赞 timgeb 4/20/2018
在 Python 3.4 及更高版本中,有 .这是一个演示。struct.iter_unpack