【问题标题】:Ruby unpack to PythonRuby 解压到 Python
【发布时间】:2012-07-12 08:13:09
【问题描述】:

我正在尝试将一些 Ruby 代码转换为 Python。我在这条线上遇到了麻烦:

Digest::MD5.digest(message).unpack('L*')

我想我应该使用struct 模块和hashlib 一个,但如果我这样做:

struct.unpack('L', hashlib.md5(message).digest())

我收到此错误:

struct.error: unpack requires a bytes object of length 4

我该怎么办? 谢谢你,

魔方

附:输出应该是一个 4 x 32 位整数的列表:

irb(main):039:0> Digest::MD5.digest('Hash').unpack('L*')
=> [631892218, 1967199614, 3683860954, 4130231798]

【问题讨论】:

  • 你试过struct.unpack('LLLL', hashlib.md5(message).digest())吗?如果这不起作用,请提供您的消息样本。
  • @ThomasOrozco:哇,它有效!你能解释一下LLLL的格式吗?谢谢!
  • LLLL 表示“4 个 32 位整数”。因此,如果您想要 4 个 32 位整数,则使用 LLLL 格式而不是 L 格式,后者只有 1 个 32 位整数。
  • @ThomasOrozco:太好了!谢谢!

标签: python ruby struct unpack


【解决方案1】:

不支持任意长度的解包(* 运算符)。您必须手动指定中继器。

幸运的是,struct 模块确实允许您指定固定长度,并且 hashlib 模块告诉您预期的字节数。通过在L 之前放置一个整数,您可以指定应用该模式的次数。 hashlib 库中的特定散列有一个 .digest_size attribute,它告诉您特定散列的长度是多少字节。

组合这些:

structspec = '%iL' % (hashlib.hash('md5').digest_size / 4)
struct.unpack(structspec, hashlib.md5(message).digest())

如果您甚至不想在那里硬编码4,您也可以向struct.calcsize 询问L unsigned long 的大小:

structspec = '%iL' % (hashlib.hash('md5').digest_size / struct.calcsize('L'))
struct.unpack(structspec, hashlib.md5(message).digest())

事实上,在像我的 Mac 这样的 64 位平台上,L 是 8 个字节,因此如果您要跨不同架构进行部署,后一种计算非常重要。

【讨论】:

    【解决方案2】:

    struct.unpack('L', ...) 只会从参数中解压缩一个 long。您要做的是全部提取,与 Ruby 不同,Python 的解包函数无法解包任意数量的值,而是必须重复格式说明符。

    hash = hashlib.md5(message).digest()
    struct.unpack('L' * (len(hash) / 4), hash)
    

    这将在字符串允许的范围内重复'L' 并解压缩散列中的所有整数并返回一个包含 len / 4 项的元组。如果您希望将结果作为列表,只需使用list() 将其转换为一个。

    【讨论】:

    • 或者,'nL' 也可以使用,n 是一个整数。
    【解决方案3】:

    如果您确定要 4 个 long,格式为 'LLLL':

    struct.unpack('LLLL', hashlib.md5(message).digest())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多