1

在手动清除可移动 USB 驱动器上损坏的回收站后,我发现我最近执行的几个 Python 文件也损坏了;用编辑器打开它们会显示它们的全部内容都填充了空字节(所有00s)。我不知道这是怎么发生的,但无论如何,不​​幸的是,我的最后一次备份要追溯到几周前,所以如果可能的话,我想尝试恢复丢失的源文件。

我在其中找到了相关的.pyc(日期为损坏前一天)文件.\__pycache__\,我正在尝试.py从二进制文件中重建一个人类可读、准备执行的文件,但到目前为止我还没有取得太大的成功。

许多类似的搜索都会找到诸如uncompyle6decompyle3 之类的工具,但这些工具都不支持 Python 3.10,并且他们的开发人员表示他们也不打算维护它们。

似乎唯一一个与字节码反编译远程相关的工具/包也支持 Python 3.10 是unpyc3 的这个分支,但它似乎在实际代码(或代码对象;我不完全确定)上运行。

希望这个工具是我恢复代码的关键,这就是我自己取得的成就:

from unpyc3 import decompile
import dis, marshal

with open("thermo.cpython-310.pyc", "rb") as f:
    f.seek(16) # By all accounts this should be 8 bytes, but 16 is the only way I have successfully been able to read the bytecode
    
    raw = f.read()
    code = marshal.loads(raw)

with open("disassembly.txt", "w", encoding="utf-8") as out:
    dis.dis(code, file=out)

encoding="utf-8" 因为我的一些变量是Unicode 字符(例如 α、λ、φ 等),所以在过程中的某个地方需要。

这将我认为是一系列 CPythonInstruction实例写入disassembly.txt,我在下面复制了其中的一个片段:

   2           0 LOAD_CONST               0 (0)
               2 LOAD_CONST               1 (None)
               4 IMPORT_NAME              0 (Constants)
               6 STORE_NAME               0 (Constants)

   3           8 LOAD_CONST               0 (0)
              10 LOAD_CONST               1 (None)
              12 IMPORT_NAME              1 (EOS)
              14 STORE_NAME               1 (EOS)

   4          16 LOAD_CONST               0 (0)
              18 LOAD_CONST               1 (None)
              20 IMPORT_NAME              2 (ACM)
              22 STORE_NAME               2 (ACM)

   7          24 LOAD_CONST               0 (0)
              26 LOAD_CONST               2 (('sqrt', 'exp', 'log'))
              28 IMPORT_NAME              3 (math)
              30 IMPORT_FROM              4 (sqrt)
              32 STORE_NAME               4 (sqrt)
              34 IMPORT_FROM              5 (exp)
              36 STORE_NAME               5 (exp)
              38 IMPORT_FROM              6 (log)
              40 STORE_NAME               6 (log)
              42 POP_TOP

我试图恢复的实际源文件thermo.py将近 3000 行,所以我不会在这里重现整个输出(我也不认为我可以在任何地方复制,因为它超过了 Pastebin 的 512 kB 的免费限制)。

这似乎是正确的信息,但是一旦我们到达这个与汇编相邻的代码,我的编程经验就完全枯竭了,老实说,我对下一步感到茫然。似乎unpyc3.decompile()接受 Python module、 Pythonfunction或 CPythonPyCodeObject作为输入,但 unpyc3 的文档不是很详细。

所以我现在的问题是:

  • 如果我上面的编组/反汇编方法是正确的,我不知道如何处理反汇编Instruction的 s 以提供给unpyc3.decompile().

  • 如果上述方法不正确,我不知道该去哪里。

如果有人知道如何解决这个问题(或者我的目标是否真的可以实现),我会很感激任何建议。

4

0 回答 0