python-3.x - 如何使python源代码的编译可重现

标签 python-3.x pandas bytecode pyc binary-reproducibility

在我的机器上安装 jsonpickle 之后 ( pip install jsonpickle==1.4.1 --no-compile),我注意到 ext 子文件夹中的 pandas.py 文件的编译并不总是可重现的.

ext 子文件夹中,我执行了以下 bash 代码以将所有 .py 文件编译为 .pyc 文件:

python -m compileall -d somereldir --invalidation-mode checked-hash

这在 __pycache__ 子目录中创建了一个 pandas.cpython-37.pyc 文件。 在 __pycache__ 子目录中,我然后执行: xxd pandas.cpython-37.pyc > hex1.hex

如果我再次执行上述步骤并将 hexdump 写入 hex2.hex,我注意到有两行不匹配。

diff hex1.hex hex2.hex
288,289c288,289
< 000011f0: 0029 013e 0200 0000 723f 0000 00da 056e  .).>....r?.....n
< 00001200: 616d 6573 7213 0000 0029 0372 3300 0000  amesr....).r3...
---
> 000011f0: 0029 013e 0200 0000 da05 6e61 6d65 7372  .).>......namesr
> 00001200: 3f00 0000 7213 0000 0029 0372 3300 0000  ?...r....).r3...

我执行了几次,似乎有两个“版本”的 .pyc 文件,有时它们匹配,有时它们不匹配。

因此,我有几个问题:

  1. 为什么 .pyc 文件有差异?
  2. 如何确保编译后的 .pyc 文件始终相同。
  3. 我检查了其他一些 python 库,它们都生成了可重现的 .pyc 文件,那么这个 pandas.py 文件有什么不同?

最佳答案

pandas.py 文件拆分成更小的部分并进行编译后,我能够在第 135 行确定问题的位置:

name_bundle = {k: v for k, v in meta.items() if k in {'name', 'names'}}

它回答了问题:

  1. 第 135 行包含一个集合 ({'name','names'})。编译后不一定保留集合中元素的顺序。虽然dictionaries preserve insertion order as of Python 3.7 ,我找不到任何有关 Python 3.7 集合中元素顺序保存的信息。
  2. 将环境变量 PYTHONHASHSEED 设置为固定值。
  3. 这些库可能不包含任何集合。

关于python-3.x - 如何使python源代码的编译可重现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63267085/

相关文章:

java - 字节码、库和 Java

java - 在 Java 字节码中替换实例的(类)类型的优雅方法

javascript - 为什么要转换 SpiderMonkey & JSC 中的字节码?

python - 当x是一个字符串时如何 `from x import *`

python - 在 amazon/aws-cli docker 镜像上安装 python 3.9

python-3.x - 混淆矩阵 - 不随预测模型而改变 (Sklearn)

python - 我怎样才能让每次点击发生一次?

python - Pandas:改进运行时间循环遍历包含子字符串的字符串

python - 如何将新列作为字符串分配给 Pandas 分配

python - 从 Pandas 数据框索引创建列