Jak zapisać wszystkie zmienne w bieżącej sesji Pythona?

96

Chcę zapisać wszystkie zmienne w moim bieżącym środowisku Pythona. Wydaje się, że jedną z opcji jest użycie modułu „pikle”. Jednak nie chcę tego robić z 2 powodów:

  1. Muszę wywołać pickle.dump()każdą zmienną
  2. Kiedy chcę pobrać zmienne, muszę zapamiętać kolejność, w jakiej zapisałem zmienne, a następnie wykonać a, pickle.load()aby pobrać każdą zmienną.

Szukam jakiegoś polecenia, które zapisze całą sesję, aby po załadowaniu tej zapisanej sesji wszystkie moje zmienne zostały przywrócone. czy to możliwe?

Edycja: Myślę, że nie mam nic przeciwko wywołaniu pickle.dump()każdej zmiennej, którą chciałbym zapisać, ale pamiętanie dokładnej kolejności, w której zmienne zostały zapisane, wydaje się dużym ograniczeniem. Chcę tego uniknąć.

użytkownik10
źródło

Odpowiedzi:

84

Jeśli używasz półki , nie musisz pamiętać kolejności, w której obiekty są marynowane, ponieważ shelvedaje ci obiekt podobny do słownika:

Aby odłożyć swoją pracę na półkę:

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()

Przywrócić:

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]
unutbu
źródło
4
Idealny. To jest to, czego szukałem.
Swoją drogą
3
I tutaj pomyślałem, że "pikle" są zabawne! :) en.wikipedia.org/wiki/Inherently_funny_word
unutbu
1
Wiem, że ta odpowiedź jest bardzo stara, byt, kiedy to robię, mam następujący błąd: PicklingError: Can't pickle <built-in function raw_input>: it's not the same object as __builtin__.raw_inputmam tylko 2 zmienne zadeklarowane w moim obszarze roboczym. Jakieś pomysły, jak to rozwiązać? Czy po tej odpowiedzi pojawił się lepszy sposób na zapisanie bieżącej sesji?
piekło
1
Mam ten sam problem z użytkowaniem półki jak opisano powyżej. PicklingError: Can't pickle <type 'numpy.int32'>: to nie jest ten sam obiekt co numpy.int32
Pu Zhang
1
Wygląda na to, że niektórych wbudowanych funkcji i pakietów nie będzie można odłożyć na półkę, więc po prostu użyj except:zamiast except TypeError:. Pozwoli to odłożyć na półkę zmienne zdefiniowane przez użytkownika i większość obiektów (ramki danych pandy odłożone na półkę w porządku)
Nitro,
65

Po tym, jak siedziałem tutaj i nie udało mi się zapisać globals()jako słownika, odkryłem, że możesz wybrać sesję za pomocą biblioteki koperkowej.

Można to zrobić za pomocą:

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

# and to load the session again:
dill.load_session(filename)
user2589273
źródło
Nie sądzę, aby Dill zapisywał wszystkie zmienne, na przykład jeśli uruchomisz dill.dump_session () w funkcji, zmienne, które są lokalne dla tej funkcji, nie są zapisywane.
Parsa
3
To tylko kwestia zakresu, myślę, że możesz po prostu dołączyć wszystkie swoje locals () do globals (), jeśli musisz?
user2589273
Otrzymałem „TypeError: nie można wytrawiać obiektów Socket”
R. Cox,
1
Podczas zrzucania sesji TypeError: no default __reduce__ due to non-trivial __cinit__
pojawia
Próbowałem tego i stwierdziłem, że nie może zapisywać nazwanych tablic, chociaż może to być ograniczenie pikle.
rhody
6

Jeden bardzo łatwy sposób, który może zaspokoić Twoje potrzeby. Dla mnie to całkiem nieźle:

Po prostu kliknij tę ikonę w Variable Explorer (po prawej stronie Spider):

Zapisywanie wszystkich zmiennych w formacie * .spydata

Ładowanie wszystkich zmiennych lub zdjęć itp.

shm2008
źródło
Wczoraj zapisałem wszystkie zmienne w formacie .spydata i dzisiaj próbowałem zaimportować dane. Żadna zmienna nie zostanie zaimportowana :(
Bharat Ram Ammu
To działało dla mnie, ale teraz, gdy mam więcej danych, zamiast tworzyć plik Spydata, teraz tworzy plik marynowany z zerową zawartością, a także setkami plików npy. Jak mogę to otworzyć, proszę?
R. Cox
4

Oto sposób zapisywania zmiennych obszaru roboczego Spyder za pomocą funkcji 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) 

Daj mi znać, jeśli to zadziała. David BH

David BH
źródło
„NameError: name 'fpath' is not specified”: czy coś zapomniałem?
Thomas
To jest dobry pomysł. Myślałem o pożyczeniu od miejsca pracy Spydera na to samo. Ale nie wiedziałem, jak. Jednak nie do końca zrozumiałem twój kod. Czy możesz powiedzieć, czy to działa dokładnie tak, jak Spyder, że automatycznie przechwytuje wszystkie zmienne, czy też muszę określić zmienne, których chcę użyć?
cqcn1991
2

To, co próbujesz zrobić, to hibernacja procesu. To już zostało omówione . Wniosek jest taki, że istnieje kilka trudnych do rozwiązania problemów, gdy próbuje się to zrobić. Na przykład przy przywracaniu otwartych deskryptorów plików.

Lepiej jest pomyśleć o podsystemie serializacji / deserializacji dla twojego programu. W wielu przypadkach nie jest to trywialne, ale w dłuższej perspektywie jest znacznie lepszym rozwiązaniem.

Chociaż przesadziłem z problemem. Możesz spróbować wytrawić dyktowanie zmiennych globalnych . Użyj, globals()aby uzyskać dostęp do słownika. Ponieważ jest indeksowany przez zmienną nazwę, nie musisz przejmować się zamówieniem.

nkrkv
źródło
Nie. Nie próbuję hibernować procesu. Mam interaktywną powłokę Pythona, na której uruchamiam kilka skryptów i poleceń. Chcę zapisać dane wyjściowe (zmienne) niektórych z tych poleceń, aby w przyszłości, gdy będę potrzebować dostępu do danych wyjściowych, mogę po prostu uruchomić powłokę Pythona i załadować wszystkie te zmienne.
użytkownik10
Więc wytraw słownik var_name -> var_value
nkrkv
0

Jeśli chcesz, aby zaakceptowana odpowiedź była abstrakcyjna, możesz użyć:

    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())

aby pobrać / załadować obszar roboczy:

import my_pkg as mp

x=1

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

print x #print 3 for me

zadziałało, kiedy go uruchomiłem. Przyznam się, że nie rozumiem dir()iw globals()100%, więc nie jestem pewien, czy może być jakieś dziwne zastrzeżenie, ale na razie wydaje się, że działa. Komentarze są mile widziane :)


po kilku dalszych badaniach, jeśli zadzwonisz save_workspacetak, jak zasugerowałem z globalnymi i save_workspaceznajdujesz się w funkcji, nie zadziała zgodnie z oczekiwaniami, jeśli chcesz zapisać zmienne w zakresie lokalnym. Do tego zastosowania locals(). Dzieje się tak, ponieważ globals pobiera wartości globalne z modułu, w którym zdefiniowano funkcję, a nie z miejsca, w którym jest wywoływana, byłoby moim przypuszczeniem.

Pinokio
źródło
0

Możesz zapisać go jako plik tekstowy lub plik CVS. Ludzie używają Spydera na przykład do zapisywania zmiennych, ale ma on znany problem: w przypadku określonych typów danych nie można ich zaimportować.

Navid Farhoudi
źródło