Потерял важный .py файл (перезаписан в виде 0-байтного файла), но старая версия все еще загружена в IPYTHON в качестве модуля - может ли она быть восстановлена?
Из-за моей глупости, управляя несколькими различными сеансами экрана с открытым vim во многих из них, в процессе попыток "организовать" мои сеансы мне как-то удалось перезаписать очень важный .py script с файлом 0Byte,
ОДНАКО, у меня есть экземпляр ipython open, который при запуске этого же .py файла в качестве модуля все еще помнит код, который был там!
Итак, я просто изучил жесткий урок о резервных копиях (мой последний был сделан vim около недели назад, что оставило бы мне много работы), или существует ли какой-либо возможный возможный способ Извлеките файл .py из уже загруженного модуля? Я, вероятно, заслуживаю этого за то, что был таким бесцеремонным, но я серьезно отчаялся здесь.
Ответы
Ответ 1
Как отмечено в комментариях, inspect.getsource
не будет работать, потому что он зависит от исходного файла (т.е. module.__file__
).
Лучший вариант: проверьте, есть ли файл .pyc
(например, foo.pyc
должен быть рядом с foo.py
). Если есть, вы можете использовать Decompile Python 2.7.pyc, чтобы декомпилировать его.
Модули inspect
также кэшируют источник. Вы можете быть счастливы и использовать inspect.getsource(module)
, или inspect.getsourcelines(module.function)
, если он был вызван в прошлом.
В противном случае вам нужно будет перестроить модуль "вручную", проверив экспорт (т.е. module.__globals__
). Константы и многое другое очевидны, а для функций вы можете использовать func.func_name
для получения своего имени func.__doc__
, чтобы получить docstring, inspect.getargspec(func)
, чтобы получить аргументы, и func.func_code
, чтобы получить подробную информацию о коде: co_firstlineno
получит номер строки, затем co_code
получит код. Там больше об декомпиляции, что здесь: Изучение и декомпиляция байт-кода python
Например, чтобы использовать uncompyle2
:
>>> def foo():
... print "Hello, world!"
...
>>> from StringIO import StringIO
>>> import uncompyle2
>>> out = StringIO()
>>> uncompyle2.uncompyle("2.7", foo.func_code, out=out)
>>> print out.getvalue()
print 'Hello, world!'
Но нет, я не знаю более прямого метода, чтобы взять модуль и вернуть исходный код.
Ответ 2
Вы можете использовать inspect
import inspect
в сеансе Ipython и, предположив, что вы пытаетесь восстановить myModule
, выполните:
q = inspect.getsource(myModule)
и напишите q
в файл.
[Изменить]
Это помогло мне имитировать проблему, используя Python 2.7.6, IPython 1.2.1
[Изменить # 2]
![введите описание изображения здесь]()
Ответ 3
Когда процесс все еще запущен, вы можете посмотреть свое пространство имен, чтобы найти кандидатов для восстановления:
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'readline', 'rlcompleter', 'test']
Посмотрите на то, что у нас есть для test
:
>>> help(test)
Help on module test:
NAME
test
FILE
/Users/tfisher/code/ffi4wd/test.py
FUNCTIONS
call_cat(cat)
DATA
cat_name = 'commander sprinkles'
У которого есть более чистый выход, чем просмотр локалей внутри test
:
>>> dir(test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'call_cat', 'cat_name', 'json']
Используя проверить модуль, мы можем получить спецификации аргументов для функций:
>>> inspect.getargspec(test.call_cat)
ArgSpec(args=['cat'], varargs=None, keywords=None, defaults=None)
или строки внутри наших функций:
>>> inspect.getsourcelines(test.call_cat)
(['def call_cat(cat):\n', ' print("Hello %s" % cat)\n'], 5)
который достаточно близок к оригиналу:
import json
cat_name = 'commander sprinkles'
def call_cat(cat):
print("Hello %s" % cat)
Что должно работать, если файл будет удален после импорта и не был заменен файлом с тем же именем, что и более новый (getsourcelines
использует кеш объекта, если это возможно):
$ python -V
Python 2.7.10
$ ls | grep test
$