Perdu important.py fichier (écrasé en tant que Fichier 0byte), mais l'ancienne version toujours chargée dans IPYTHON en tant que module-peut - elle être récupérée?

En raison de ma stupidité, tout en gérant plusieurs sessions d'écran différentes avec vim ouvert dans beaucoup d'entre eux, en essayant d ' "organiser" mes sessions, j'ai réussi à écraser un script .PY très important avec un fichier 0Byte.

Cependant, j'ai une instance ipython ouverte qui, lors de l'exécution de ce même fichier .py en tant que module, se souvient toujours du code qui était là!

Je viens donc d'apprendre une dure leçon sur les sauvegardes (ma dernière a été faite par vim il y a environ une semaine, ce qui me laisserait beaucoup de travail à faire), ou Existe-t-il un moyen possible et concevable de récupérer le fichier .py à partir d'un module déjà chargé? je le mérite probablement pour être si cavalier, mais je suis sérieusement désespéré ici.

21
demandé sur Luke Davis 2015-07-29 20:46:44

3 réponses

Comme indiqué dans les commentaires, inspect.getsource ne fonctionnera pas, car cela dépend du fichier d'origine (c'est à dire, module.__file__).

Meilleure option: vérifiez s'il y a un fichier .pyc (ex, foo.pyc devrait être à côté de foo.py). Si c'est le cas, vous pouvez utiliser décompiler Python 2.7 .pyc pour le décompiler.

Les modules inspect mettent également en cache la source. Vous pouvez avoir de la chance et utiliser inspect.getsource(module), ou inspect.getsourcelines(module.function) s'il a été appelé dans le passé.

Sinon, vous devrez reconstruire le module "manuellement" en inspection des exportations (ie, module.__globals__). Constantes et autres joyeusetés sont évidentes, et pour les fonctions que vous pouvez utiliser func.func_name pour obtenir son nom, func.__doc__ pour obtenir la docstring, inspect.getargspec(func) pour obtenir les arguments, et func.func_code pour obtenir des détails sur le code: co_firstlineno obtiendrez le numéro de la ligne, puis co_code obtiendrez le code. Il y a plus sur la décompilation ici: Explorer et décompiler le bytecode python

Par exemple, Pour utiliser 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!'

Mais, Non-Je ne suis pas au courant de plus simple méthode pour prendre un module et récupérer le code source.

22
répondu David Wolever 2017-05-23 12:14:50

Avec le processus toujours en cours d'exécution, vous pouvez consulter votre espace de noms pour trouver des candidats à restaurer:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'readline', 'rlcompleter', 'test']

Jetons un coup d'oeil à ce que nous avons en réserve pour 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'

Qui a une sortie plus propre que de regarder les locaux à l'intérieur de test:

>>> dir(test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'call_cat', 'cat_name', 'json']

En utilisant le module inspect , nous pouvons obtenir les spécifications d'argument pour les fonctions:

>>> inspect.getargspec(test.call_cat)
ArgSpec(args=['cat'], varargs=None, keywords=None, defaults=None)

, Ou les lignes à l'intérieur de nos fonctions:

>>> inspect.getsourcelines(test.call_cat)
(['def call_cat(cat):\n', '    print("Hello %s" % cat)\n'], 5)

Qui est raisonnablement proche de la original:

import json

cat_name = 'commander sprinkles'

def call_cat(cat):
    print("Hello %s" % cat)

Qui devrait fonctionner si le fichier est supprimé après avoir été importé et n'a pas été remplacé par un fichier du même nom plus récent (getsourcelines utilise le cache d'objets si possible):

$ python -V
Python 2.7.10

$ ls | grep test
$
1
répondu 2015-07-29 18:19:46

Vous devriez pouvoir utiliser inspect

Importez inspect dans votre session Ipython, et, en supposant que vous essayez de récupérer myModule, Faites:

q = inspect.getsource(myModule)

Et écrire q dans un fichier.

[modifier] Cela a fonctionné pour moi en simulant le problème en utilisant Python 2.7.6, IPython 1.2.1

[Modifier #2]

entrez la description de l'image ici

0
répondu Ryan 2015-07-29 18:33:14