จะบันทึกตัวแปรทั้งหมดในเซสชัน python ปัจจุบันได้อย่างไร?


96

ฉันต้องการบันทึกตัวแปรทั้งหมดในสภาพแวดล้อม python ปัจจุบันของฉัน ดูเหมือนว่าทางเลือกหนึ่งคือการใช้โมดูล 'ดอง' อย่างไรก็ตามฉันไม่ต้องการทำสิ่งนี้ด้วยเหตุผล 2 ประการ:

  1. ฉันต้องเรียกpickle.dump()หาตัวแปรแต่ละตัว
  2. เมื่อฉันต้องการดึงตัวแปรฉันต้องจำลำดับที่ฉันบันทึกตัวแปรจากนั้นทำpickle.load()เพื่อดึงข้อมูลแต่ละตัวแปร

ฉันกำลังมองหาคำสั่งบางอย่างที่จะบันทึกทั้งเซสชันดังนั้นเมื่อฉันโหลดเซสชันที่บันทึกไว้นี้ตัวแปรทั้งหมดของฉันจะถูกเรียกคืน เป็นไปได้หรือไม่

แก้ไข: ฉันเดาว่าฉันไม่คิดจะเรียกpickle.dump()ตัวแปรแต่ละตัวที่ฉันต้องการบันทึก แต่การจำลำดับที่แน่นอนในการบันทึกตัวแปรนั้นดูเหมือนเป็นข้อ จำกัด ที่ยิ่งใหญ่ ฉันต้องการหลีกเลี่ยงสิ่งนั้น

คำตอบ:


84

หากคุณใช้ชั้นวางคุณไม่จำเป็นต้องจำลำดับที่วัตถุถูกดองเนื่องจากshelveจะทำให้คุณมีวัตถุคล้ายพจนานุกรม:

เพื่อเก็บงานของคุณ:

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

ในการกู้คืน:

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]

4
สมบูรณ์แบบ. นี่คือสิ่งที่ฉันกำลังมองหา BTW ฉันพบประโยคนี้ในโพสต์ของคุณตลกสุด ๆ : "To
Shelve your

3
และที่นี่ฉันคิดว่า "ผักดอง" เป็นเรื่องตลก! :) en.wikipedia.org/wiki/Inherently_funny_word
unutbu

1
ฉันรู้ว่าคำตอบนี้เก่ามากเมื่อฉันทำสิ่งนี้ฉันมีข้อผิดพลาดต่อไปนี้: PicklingError: Can't pickle <built-in function raw_input>: it's not the same object as __builtin__.raw_inputฉันมีตัวแปร 2 ตัวที่ประกาศในพื้นที่ทำงานของฉัน มีความคิดเกี่ยวกับวิธีแก้ปัญหานี้หรือไม่? มีวิธีที่ดีกว่าในการบันทึกเซสชันปัจจุบันหลังจากคำตอบนี้หรือไม่?
hellter

1
ฉันมีปัญหาเดียวกันเกี่ยวกับการใช้ชั้นวางตามที่อธิบายไว้ข้างต้น PicklingError: ไม่สามารถดอง <type 'numpy.int32'>: ไม่ใช่วัตถุเดียวกันกับ numpy.int32
Pu Zhang

1
ดูเหมือนว่าฟังก์ชั่นในตัวบางและแพคเกจจะไม่สามารถที่จะมีมติดังนั้นเพียงใช้แทนexcept: except TypeError:สิ่งนี้จะเก็บตัวแปรที่ผู้ใช้กำหนดและอ็อบเจ็กต์ส่วนใหญ่ (เฟรมข้อมูลแพนด้าถูกเก็บไว้อย่างดีสำหรับฉัน)
Nitro

65

หลังจากนั่งที่นี่และไม่สามารถบันทึกglobals()เป็นพจนานุกรมได้ฉันพบว่าคุณสามารถดองเซสชันโดยใช้ห้องสมุดผักชีฝรั่ง

สามารถทำได้โดยใช้:

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

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

ฉันไม่คิดว่าผักชีลาวจะบันทึกตัวแปรทั้งหมดเช่นถ้าคุณเรียกใช้ dill.dump_session () ในตัวแปรฟังก์ชันซึ่งเป็นฟังก์ชันภายในของฟังก์ชันนั้นจะไม่ถูกบันทึก
Parsa

3
นั่นเป็นเพียงปัญหาเกี่ยวกับขอบเขตฉันเดาว่าคุณสามารถต่อท้ายพื้นที่ทั้งหมดของคุณ () กับ globals () ได้ถ้าคุณต้อง?
user2589273

ฉันได้รับ "TypeError: can't pickle Socket objects"
R. Cox

1
ฉันได้รับข้อผิดพลาดประเภทต่อไปนี้เมื่อทิ้งเซสชัน: TypeError: no default __reduce__ due to non-trivial __cinit__
Kareem Jeiroudi

ฉันลองสิ่งนี้และพบว่าไม่สามารถบันทึกอาร์เรย์ที่มีชื่อได้แม้ว่านี่อาจเป็นข้อ จำกัด ในการดอง
rhody

6

วิธีง่ายๆวิธีหนึ่งที่อาจตอบสนองความต้องการของคุณ สำหรับฉันมันทำได้ค่อนข้างดี:

เพียงคลิกที่ไอคอนนี้บน Variable Explorer (ด้านขวาของ Spider):

บันทึกตัวแปรทั้งหมดในรูปแบบ * .spydata

กำลังโหลดตัวแปรหรือรูปภาพทั้งหมดเป็นต้น


ฉันบันทึกตัวแปรทั้งหมดในรูปแบบ. spydata เมื่อวานนี้และฉันพยายามนำเข้าข้อมูลวันนี้ ไม่มีการนำเข้าตัวแปร :(
Bharat Ram Ammu

สิ่งนี้ใช้ได้ผลสำหรับฉัน แต่ตอนนี้ฉันมีข้อมูลมากขึ้นแทนที่จะสร้างไฟล์ Spydata ตอนนี้ทำให้ไฟล์ดองที่มีเนื้อหาเป็นศูนย์และไฟล์ npy หลายร้อยไฟล์ ฉันจะเปิดสิ่งเหล่านี้ได้อย่างไร
อาร์คอคส์

4

นี่คือวิธีการบันทึกตัวแปรพื้นที่ทำงาน Spyder โดยใช้ฟังก์ชัน 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) 

แจ้งให้เราทราบหากวิธีนี้เหมาะกับคุณ เดวิด BH


"NameError: name 'fpath' is not defined": ฉันลืมอะไรไปหรือเปล่า?
Thomas

นั่นเป็นความคิดที่ดี. ฉันกำลังคิดเกี่ยวกับการยืมจากพื้นที่ทำงานของสปายเดอร์สำหรับสิ่งเดียวกัน แต่คิดไม่ออกว่าเป็นอย่างไร อย่างไรก็ตามฉันไม่ค่อยเข้าใจรหัสของคุณ คุณช่วยบอกได้ไหมว่ามันทำงานเหมือนกับ Spyder ที่จับตัวแปรทั้งหมดโดยอัตโนมัติหรือฉันต้องระบุตัวแปรที่ฉันต้องการใช้
cqcn1991

2

สิ่งที่คุณพยายามทำคือจำศีลกระบวนการของคุณ นี่คือการพูดคุยกันแล้ว ข้อสรุปก็คือมีปัญหาที่ยากต่อการแก้ไขหลายประการขณะพยายามดำเนินการดังกล่าว ตัวอย่างเช่นการกู้คืนตัวอธิบายไฟล์ที่เปิด

จะดีกว่าถ้าคิดเกี่ยวกับระบบย่อย serialization / deserialization สำหรับโปรแกรมของคุณ ไม่ใช่เรื่องเล็กน้อยในหลาย ๆ กรณี แต่เป็นวิธีแก้ปัญหาที่ดีกว่าในมุมมองระยะยาว

แม้ว่าถ้าฉันพูดเกินจริงปัญหา คุณสามารถลองดองตัวแปรทั่วโลกของคุณDict ใช้globals()เพื่อเข้าถึงพจนานุกรม เนื่องจากเป็น varname-index คุณจึงไม่ต้องกังวลเกี่ยวกับคำสั่งซื้อ


นพส. ฉันไม่ได้พยายามจำศีลกระบวนการนี้ ฉันมี python shell แบบโต้ตอบซึ่งฉันเรียกใช้สคริปต์และคำสั่งต่างๆ ฉันต้องการบันทึกผลลัพธ์ (ตัวแปร) ของคำสั่งเหล่านี้บางคำสั่งดังนั้นในอนาคตเมื่อใดก็ตามที่ฉันต้องการเข้าถึงเอาต์พุตฉันสามารถยิงไพ ธ อนเชลล์และโหลดตัวแปรเหล่านี้ทั้งหมดได้
10

ดังนั้นดองพจนานุกรม var_name -> var_value
nkrkv

0

หากคุณต้องการให้คำตอบที่ยอมรับเป็นนามธรรมเป็นฟังก์ชันคุณสามารถใช้:

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

เพื่อรับ / โหลดพื้นที่ทำงาน:

import my_pkg as mp

x=1

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

print x #print 3 for me

มันใช้งานได้เมื่อฉันวิ่ง ฉันยอมรับว่าฉันไม่เข้าใจdir()และglobals()100% ดังนั้นฉันจึงไม่แน่ใจว่าอาจมีข้อแม้แปลก ๆ หรือไม่ แต่จนถึงตอนนี้ดูเหมือนว่าจะใช้งานได้ ยินดีรับฟังความคิดเห็น :)


หลังจากการวิจัยเพิ่มเติมหากคุณโทรsave_workspaceตามที่ฉันแนะนำด้วย globals และsave_workspaceอยู่ในฟังก์ชันมันจะไม่ทำงานตามที่คาดไว้หากคุณต้องการบันทึกข้อมูลที่สามารถใช้ได้ในขอบเขตท้องถิ่น สำหรับการใช้งานlocals()นั้น สิ่งนี้เกิดขึ้นเนื่องจาก globals ใช้ globals จากโมดูลที่มีการกำหนดฟังก์ชั่นไม่ใช่จากที่ที่เรียกว่าเป็นการเดาของฉัน


0

คุณสามารถบันทึกเป็นไฟล์ข้อความหรือไฟล์ CVS ตัวอย่างเช่นผู้คนใช้ Spyder ในการบันทึกตัวแปร แต่มีปัญหาที่ทราบ: สำหรับข้อมูลบางประเภทจะไม่สามารถนำเข้าในท้องถนนได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.