Подтвердить что ты не робот

Потерял важный .py файл (перезаписан в виде 0-байтного файла), но старая версия все еще загружена в IPYTHON в качестве модуля - может ли она быть восстановлена?

Из-за моей глупости, управляя несколькими различными сеансами экрана с открытым vim во многих из них, в процессе попыток "организовать" мои сеансы мне как-то удалось перезаписать очень важный .py script с файлом 0Byte,

ОДНАКО, у меня есть экземпляр ipython open, который при запуске этого же .py файла в качестве модуля все еще помнит код, который был там!

Итак, я просто изучил жесткий урок о резервных копиях (мой последний был сделан vim около недели назад, что оставило бы мне много работы), или существует ли какой-либо возможный возможный способ Извлеките файл .py из уже загруженного модуля? Я, вероятно, заслуживаю этого за то, что был таким бесцеремонным, но я серьезно отчаялся здесь.

4b9b3361

Ответ 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
$