比较两个 python 文件是否产生相同的字节码(代码是否相同)

compare whether two python files result in same byte code (are code wise identical)

我们正在进行一些代码清理。 清理只是关于格式化(如果有问题,那么我们甚至可以假设,行号不会改变,但理想情况下我也想忽略行号的变化)

为了确保没有意外的代码更改,我想找到一种简单/快速的方法来比较两个源代码。

所以让我们假设,我有 file1.pyfile2.py

有效的是使用 py_compile.compile(filename) 创建 .pyc 文件然后使用 uncompyle6 pycfile,然后去掉注释比较结果, 但这太过分了而且非常慢。

我想象的另一种方法是复制 file1.py 例如 file.py, 使用 py_compile.compile("file.py") 并保存 .pyc 文件

然后复制 file2.py 例如到 file.py 并使用 使用 py_compile.compile("file.py") 并保存 .pyc 文件 最后比较两个生成的 .pyc 文件

这是否适用于所有(当前)版本 >= python 3.6

如果我至少记得 python2,pyc 文件可能包含时间戳或绝对路径,这可能会使比较失败。 (至少如果 pyc 文件的生成是 运行 在两台不同的机器上)

有没有一种干净的方法来比较py2文件的字节码?

作为奖励功能(如果可能的话)我想为每个字节码创建一个哈希,我可以存储它以供将来参考。

可能不是想要的答案 - 但您为什么不使用 diff 工具来比较文件是否已更改? https://linuxhandbook.com/diff-command/

如果文件被更改,请使用像 meld 这样的合并工具来比较更改 http://meldmerge.org/

您可以尝试使用 Python 的内部 compile function,它可以从字符串编译(在您的情况下从文件中读入)。例如,编译和比较来自两个等效程序和一个几乎等效程序的结果代码对象,然后仅出于演示目的(您 不想做的事情)执行一些代码对象:

import hashlib
import marshal
​
​
def compute_hash(code):
    code_bytes = marshal.dumps(code)
    code_hash = hashlib.sha1(code_bytes).hexdigest()
    return code_hash
​
​
source1 = """x = 3
y = 4
z = x * y
print(z)
"""
source2 = "x=3;y=4;z=x*y;print(z)"
​
source3 = "a=3;y=4;z=a*y;print(z)"
​
obj1 = compile(source=source1, filename='<string>', mode='exec', dont_inherit=1)
obj2 = compile(source=source2, filename='<string>', mode='exec', dont_inherit=1)
obj3 = compile(source=source3, filename='<string>', mode='exec', dont_inherit=1)
​
print(obj1 == obj2)
print(obj1 == obj3)
​
exec(obj1)
exec(obj3)
print(compute_hash(obj1))

打印:

True
False
12
12
48632a1b64357e9d09d19e765d3dc6863ee67ab9

这将使您免于复制 py 文件、创建 pyc 文件、比较 pyc 文件等操作

注:

如果您需要可重复的散列函数,即 returns 在连续的程序运行中计算相同的代码对象时,compute_hash 函数会重复使用相同的值。