[recovery mode] Как спасти потерянный исходный код на Python, если он все еще не выгружен из памяти

Это перевод вчерашней заметки от Simon Willison

Я облажался, бездумно используя git (git checkout -- — не на том файле) и умудрился удалить код, который я только что написал…, но он все еще был загружен в исполняемый процесс в докер-контейнере. Вот, как я восстановил код, используя https://pypi.python.org/pypi/pyrasite/ и https://pypi.python.org/pypi/uncompyle6


Подключите удаленный шелл к докеру


Установите GDB (это требует pyrasite)


apt-get update && apt-get install gdb

Установите pyrasite — это позволит подключить питоновкий шелл к запущенному процессу


pip install pyrasite

Установите uncompyle6, это позволит декомпилировать объекты в памяти обратно в питоновский код


pip install uncompyle6

Отыщите PID процесса, который исполняет ваш код


ps aux | grep python

Подключите интерактивный шелл используя pyrasite


pyrasite-shell 

Итак, у нас есть интерактивный питоновский шелл! Импортируйте код, который необходимо восстановить


>>> from my_package import my_module

Определите, какие функции и классы мы восстанавливаем


>>> dir(my_module)
['MyClass', 'my_function']

Декомпилируйте функции в исходный код


>>> import uncompyle6
>>> import sys
>>> uncompyle6.main.uncompyle(
    2.7, my_module.my_function.func_code, sys.stdout
)
# uncompyle6 version 2.9.10
# Python bytecode 2.7
# Decompiled from: Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
# [GCC 5.4.0 20160609]
# Embedded file name: /srv/my_package/my_module.py
function_body = "appears here"

Для классов, придется декомпилировать каждый метод по отдельности


>>> uncompyle6.main.uncompyle(
    2.7, my_module.MyClass.my_method.im_func.func_code, sys.stdout
)
# uncompyle6 version 2.9.10
# Python bytecode 2.7
# Decompiled from: Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
# [GCC 5.4.0 20160609]
# Embedded file name: /srv/my_package/my_module.py
class_method_body = "appears here"

Вот он, ваш было почти утерянный код.

Комментарии (3)

  • 12 марта 2017 в 17:45

    0

    Проще положить исходники в dropbox. Хотя конечно, если дропбокс не успел синхронизировать файлы — придётся изворачиваться именно так. Да и CPU и fs дропбокс нагружает очень не слабо, если много папок.

  • 12 марта 2017 в 17:52

    0

    А разве нельзя взять *.pyc файлы и декомпилировать те которые вам нужны?
    • 12 марта 2017 в 17:55

      +1

      Можно, конечно, если они есть. Там в самом начале описан юзкейс и я в него попадал сам: мне показалось, что пошаговая инструкция заслуживает того, чтобы попасть в закладки.

© Habrahabr.ru