2010-06-02 14 views
49

Je veux enregistrer toutes les variables dans mon environnement Python actuel. Il semble qu'une option consiste à utiliser le module 'pickle'. Cependant, je ne veux pas faire cela pour 2 raisons:Comment sauvegarder toutes les variables de la session Python actuelle?

1) Je dois appeler pickle.dump() pour chaque variable
2) Lorsque je veux récupérer les variables, il faut se rappeler l'ordre que j'ai sauvegardé les variables, puis faire un pickle.load() pour récupérer chaque variable.

Je cherche une commande qui permettrait d'enregistrer la session entière, de sorte que lorsque je charge cette session sauvegardée, toutes mes variables sont restaurées. Est-ce possible?

Merci beaucoup!
Gaurav

Edit: Je pense que je ne me dérange pas d'appeler pickle.dump() pour chaque variable que je voudrais sauver, mais se souvenant de l'ordre exact dans lequel les variables ont été enregistrées semble comme une grande restriction. Je veux éviter cela.

Répondre

53

Si vous utilisez shelve, vous ne devez pas se rappeler l'ordre dans lequel les objets sont décapés, puisque shelve vous donne un objet comme dictionnaire:

Pour SHELVE votre travail:

import shelve 

T='Hiya' 
val=[1,2,3] 

filename='/tmp/shelve.out' 
my_shelf = shelve.open(filename,'n') # 'n' for new 

for key in dir(): 
    try: 
     my_shelf[key] = globals()[key] 
    except TypeError: 
     # 
     # __builtins__, my_shelf, and imported modules can not be shelved. 
     # 
     print('ERROR shelving: {0}'.format(key)) 
my_shelf.close() 

pour restaurer:

my_shelf = shelve.open(filename) 
for key in my_shelf: 
    globals()[key]=my_shelf[key] 
my_shelf.close() 

print(T) 
# Hiya 
print(val) 
# [1, 2, 3] 
+1

Parfait. C'est ce que je cherchais. BTW, je trouve cette phrase dans votre message super drôle: "Pour mettre votre travail à l'écart" :) – user10

+0

Et là, je pensais que "cornichons" étaient drôles! :) http://en.wikipedia.org/wiki/Inherently_funny_word – unutbu

+0

est-il possible d'abstraire les détails de l'enregistrement des variables dans une fonction séparée? Par exemple, lorsque vous faites défiler les noms dans l'espace de nom local actuel, vous pouvez le passer en argument, mais comment passez-vous les globals? Avez-vous aussi besoin de passer les globals? comme dans 'save (dir(), globals())', puis exécutez votre code ci-dessus? Aussi est-il possible de simplement appeler une fonction qui abstrait de restauration? – Pinocchio

2

Ce que vous essayez de faire est d'hiberner votre processus. C'était déjà discussed. La conclusion est qu'il existe plusieurs problèmes difficiles à résoudre en essayant de le faire. Par exemple avec la restauration des descripteurs de fichiers ouverts.

Il est préférable de penser au sous-système de sérialisation/désérialisation de votre programme. Ce n'est pas trivial dans de nombreux cas, mais c'est une meilleure solution dans une perspective à long terme. Bien que si j'ai exagéré le problème. Vous pouvez essayer de décaper vos variables globales dict. Utilisez globals() pour accéder au dictionnaire. Puisque c'est varname-indexed vous n'avez pas à vous soucier de la commande.

+0

NOPES. Je n'essaie pas d'hiberner le processus. J'ai un shell python interactif sur lequel je cours plusieurs scripts et commandes. Je veux enregistrer la sortie (variables) de certaines de ces commandes, de sorte qu'à l'avenir, chaque fois que j'ai besoin d'accéder à la sortie, je peux lancer un shell python et charger toutes ces variables. – user10

+0

Alors, pickle le dictionnaire var_name -> var_value – nkrkv

+0

Merci pour votre réponse! – user10

3

Voici une façon enregistrer les variables de l'espace de travail Spyder en utilisant les fonctions de spyderlib

#%% Load data from .spydata file 
from spyderlib.utils.iofuncs import load_dictionary 

globals().update(load_dictionary(fpath)[0]) 
data = load_dictionary(fpath) 



#%% Save data to .spydata file 
from spyderlib.utils.iofuncs import save_dictionary 
def variablesfilter(d): 
    from spyderlib.widgets.dicteditorutils import globalsfilter 
    from spyderlib.plugins.variableexplorer import VariableExplorer 
    from spyderlib.baseconfig import get_conf_path, get_supported_types 

    data = globals() 
    settings = VariableExplorer.get_settings() 

    get_supported_types() 
    data = globalsfilter(data,     
         check_all=True, 
         filters=tuple(get_supported_types()['picklable']), 
         exclude_private=settings['exclude_private'], 
         exclude_uppercase=settings['exclude_uppercase'], 
         exclude_capitalized=settings['exclude_capitalized'], 
         exclude_unsupported=settings['exclude_unsupported'], 
         excluded_names=settings['excluded_names']+['settings','In']) 
    return data 

def saveglobals(filename): 
    data = globalsfiltered() 
    save_dictionary(data,filename) 


#%% 

savepath = 'test.spydata' 

saveglobals(savepath) 

Faites-moi savoir si cela fonctionne pour vous. David B-H

+0

"NameError: le nom 'fpath' n'est pas défini": ai-je oublié quelque chose? – Thomas

+0

C'est une bonne idée. Je pensais emprunter de l'espace de travail de spyder pour la même chose. Mais n'a pas compris comment. Cependant, je n'ai pas bien compris votre code. Pourriez-vous s'il vous plaît dire, est-ce que cela fonctionne exactement comme Spyder qui capture automatiquement toutes les variables, ou je dois spécifier les variables que je veux utiliser? – cqcn1991

25

Ayant assis ici et pas sauver le globals() comme un dictionnaire, j'ai découvert que vous pouvez décaper une session en utilisant la bibliothèque de l'aneth.

Cela peut être fait en utilisant:

import dill       #pip install dill --user 
filename = 'globalsave.pkl' 
dill.dump_session(filename) 

# and to load the session again: 
dill.load_session(filename) 
+1

Je pense que c'est la façon la plus simple, merci :) – Mohammad

+0

Je ne pense pas que l'aneth enregistre toutes les variables, par exemple si vous exécutez dill.dump_session() dans une fonction les variables qui sont locales à cette fonction ne sont pas sauvegardées. – par

+0

C'est juste un problème de portée, je suppose que vous pourriez simplement ajouter tous vos locaux() à globals() si vous devez? – user2589273

0

Si vous voulez que la réponse acceptée abstraire à la fonction que vous pouvez utiliser:

import shelve 

    def save_workspace(filename, names_of_spaces_to_save, dict_of_values_to_save): 
    ''' 
     filename = location to save workspace. 
     names_of_spaces_to_save = use dir() from parent to save all variables in previous scope. 
      -dir() = return the list of names in the current local scope 
     dict_of_values_to_save = use globals() or locals() to save all variables. 
      -globals() = Return a dictionary representing the current global symbol table. 
      This is always the dictionary of the current module (inside a function or method, 
      this is the module where it is defined, not the module from which it is called). 
      -locals() = Update and return a dictionary representing the current local symbol table. 
      Free variables are returned by locals() when it is called in function blocks, but not in class blocks. 

     Example of globals and dir(): 
      >>> x = 3 #note variable value and name bellow 
      >>> globals() 
      {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'x': 3, '__doc__': None, '__package__': None} 
      >>> dir() 
      ['__builtins__', '__doc__', '__name__', '__package__', 'x'] 
    ''' 
    print 'save_workspace' 
    print 'C_hat_bests' in names_of_spaces_to_save 
    print dict_of_values_to_save 
    my_shelf = shelve.open(filename,'n') # 'n' for new 
    for key in names_of_spaces_to_save: 
     try: 
      my_shelf[key] = dict_of_values_to_save[key] 
     except TypeError: 
      # 
      # __builtins__, my_shelf, and imported modules can not be shelved. 
      # 
      #print('ERROR shelving: {0}'.format(key)) 
      pass 
    my_shelf.close() 

    def load_workspace(filename, parent_globals): 
     ''' 
      filename = location to load workspace. 
      parent_globals use globals() to load the workspace saved in filename to current scope. 
     ''' 
     my_shelf = shelve.open(filename) 
     for key in my_shelf: 
      parent_globals[key]=my_shelf[key] 
     my_shelf.close() 

an example script of using this: 
import my_pkg as mp 

x = 3 

mp.save_workspace('a', dir(), globals()) 

pour obtenir/charger l'espace de travail:

import my_pkg as mp 

x=1 

mp.load_workspace('a', globals()) 

print x #print 3 for me 

cela a fonctionné quand je l'ai couru. Je vais admettre que je ne comprends pas dir() et globals() 100% donc je ne suis pas sûr s'il pourrait y avoir une mise en garde étrange, mais jusqu'à présent, il semble fonctionner. Les commentaires sont les bienvenus :)


après quelques recherches si vous appelez save_workspace comme je l'ai suggéré avec et globals save_workspace est dans une fonction, il ne fonctionnera pas comme prévu si vous souhaitez enregistrer les veriables dans une portée locale. Pour cela utiliser locals(). Cela arrive parce que les globals prennent les globals du module où la fonction est définie, pas d'où elle s'appelle serait ma conjecture.

-1

Je voulais ajouter un commentaire à la réponse d'unutbu, mais je n'ai pas encore assez de réputation. J'ai aussi eu le problème avec

PicklingError: Can't pickle <built-in function raw_input>: it's not the same object as __builtin__.raw_input 

Je contourné en ajoutant une règle pour passer toutes les exceptions et dites-moi ce qu'il n'a pas magasin. unubtu son code pincé, pour des raisons pratiques de copypaste:

Pour votre travail SHELVE:

import shelve 

filename='/tmp/shelve.out' 
my_shelf = shelve.open(filename,'n') # 'n' for new 

for key in dir(): 
    try: 
     my_shelf[key] = globals()[key] 
    except TypeError: 
     # 
     # __builtins__, my_shelf, and imported modules can not be shelved. 
     # 
     print('TypeError shelving: {0}'.format(key)) 
    except: 
     # catches everything else 
     print('Generic error shelving: {0}'.format(key)) 
my_shelf.close() 

Pour restaurer:

my_shelf = shelve.open(filename) 
for key in my_shelf: 
    globals()[key]=my_shelf[key] 
my_shelf.close() 
Questions connexes