Python中的解包格式字符

5

我需要将这个Perl字符串转换为Python代码:

unpack("nNccH*", string_val)

我需要将 nNccH* 数据格式转换为Python格式字符。
在Perl中,二进制数据会解包到五个变量中:
  • “网络”(大端)16位值
  • “网络”(大端)32位值
  • 有符号char(8位整数)值
  • 有符号char(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编写过程序,但是我的当前任务是编写一个多线程Python服务器,之前是用Perl编写的...


我可以找到除了H之外的所有等效内容,对于H,我会假设您将使用p或s进行操作。 - Senthil Kumaran
你需要计算字符串的大小,这个答案可能会有所帮助。http://stackoverflow.com/a/5849224/70350 - pojo
"while DataByte = client[0].recv(1):" 不是 Python 语法,这段代码永远不会起作用。 - S.Lott
据我所知,*只是表示“剩下的所有元素”,因此他可以在H*之前解包所有内容,然后只需获取剩余部分而不进行解包。 - Eli Bendersky
顺便说一下,D先生,感谢您编辑和澄清问题。然而,正如S.Lott所指出的那样,最后的代码片段没有多少意义。 - Eli Bendersky
请参考此问题,了解如何重复应用格式字符串! - timgeb
2个回答

8
Perl格式"nNcc"的Python格式等效为"!HLbb"。 Python中没有直接对应于Perl的"H*"
存在两个问题:
  • Python的struct.unpack不接受通配符字符*
  • Python的struct.unpack不会将数据字符串“hexlify”
第一个问题可以使用辅助函数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.
    """
    # https://dev59.com/LlzUa4cB1Zd3GeqP34E3#7867892
    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']

str.encode("hex")binascii.hexlify() 的一种替代方法。 - Sven Marnach
1
如果您想要 Python 3 兼容性,计算 n 时需要使用 //,否则 str(n) 将会产生 '16.0' 并破坏格式字符串。 - Mark Tolonen
在Python 3.4及更高版本中,有struct.iter_unpack这里有一个演示。 - timgeb

7

你需要找的Python函数是 struct.unpack。这里有关于格式字符串的文档: http://docs.python.org/library/struct.html

如果你能具体说明需要什么样的拆包,那么得到帮助的机会会更大。并不是每个人都了解Perl。


谢谢。我已经阅读了Perl和Python的解包文档。但是到目前为止,我还不理解一些细节。 - Sir D
@Eli - 直接翻译可能会有一些小问题。例如,在Python中如何执行H*?我想用户本可以更好地表达问题。 - Senthil Kumaran
@SenthilKumaran:请注意,用户在我的回答之后编辑了问题。在编辑之前,他没有说明Perl中格式字符的含义。 - Eli Bendersky
@SirD:“到目前为止,我还不理解一些细节。” 请具体说明您不理解的内容。请更新问题并说明您不理解的内容。 - S.Lott

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