首页 > 解决方案 > 检查两个 .pyc 文件(使用相同的 python 版本编译)是否包含相同的代码

问题描述

问题是相似的,但与比较两个 python 文件是否产生相同的字节码(代码相同)不同

事实上我有一个解决方案,但它不是那么优雅:

假设我.pyc在一台机器上创建了一些.pyc文件,在另一台机器上创建了一些文件。我假设这些.pyc文件是使用相同版本的 python 创建的。

否则我不得不使用一个慢得多的工具,比如uncompyle6.

如何验证两者都包含相同的字节码?

我有两个问题将在下面提到:

  1. 读入.pyc文件:

    这里没问题。

    import marshal
    import hashlib
    
    def calc_pyc_hash(pyc_fname):
        with open(pyc_fname, "rb") as fin:
            pyc_data = fin.read()
    
  2. 问题 1:剥离标头字节并提取代码对象这是一个问题,因为要剥离的字节量似乎取决于 python 版本。有没有一种简单的方法来以编程方式获得正确的值?

    我的解决方法:(代码仍然是的一部分calc_pyc_hash

       for offs in range(8, 20):
           try:
               code = marshal.loads(pyc_data[offs:])
               print("offset of %d bytes for %s" % (offs, sys.version_info))
               break
           except Exception:
               pass
       else:
           print("no solution found")    sys.exit(-1)
    
  3. 问题2:如何忽略字段co_filename。代码对象有一个字段co_filename,它是编译后的 python 文件的名称。不幸的是,这个名称可能是一个带有绝对路径的文件名,这可能会根据.pyc文件的创建位置和方式而有所不同。我发现的唯一方法是遵循(代码仍然是其中的一部分calc_pyc_hash):

        code_bytes = []
        fields = [name for name in dir(code) if name.startswith("co_") 
                  and name != "co_filename"]
        for fieldname in fields:
            code_bytes.append(marshal.dumps(getattr(code, fieldname)))
    
        code_bytes = b"".join(code_bytes)
        hashval = hashlib.sha1(code_bytes).hexdigest()
        return hashval
    

我认为不是很优雅的是,我必须猜测要跳过的标头字节的数量,并且我必须剥离文件名并连接其他字段的数据。

有没有人有更优雅的解决方案?

标签: pythoncomparisonpyc

解决方案


推荐阅读