Persistent data for ghpython component menu options

What is a method to store a component variable data such that when the file is reloaded or the computer is restarted, the component can recall this variable data.

(for example a right-click menu selection by the user on the component)

def AppendAdditionalComponentMenuItems(self, menu):
    item = Grasshopper.Kernel.GH_Component.Menu_AppendGenericMenuItem(
        menu, "Option a", self.OnClicked_a, self.Icon_24x24, None, True, False);
    item.ToolTipText = "Option a";
    item2 = Grasshopper.Kernel.GH_Component.Menu_AppendGenericMenuItem(
        menu, "Option b", self.OnClicked_b, self.Icon_24x24, None, True, False);
    item2.ToolTipText = "Option b";
    
def OnClicked_a(self, obj, args):
    try:
        self.StateChange(obj, args, name="Option a", typ=0)
    except Exception, ex:
        System.Windows.Forms.MessageBox.Show(str(ex))

def OnClicked_b(self, obj, args):
    try:
        self.StateChange(obj, args, name="Option b", typ=1)
    except Exception, ex:
        System.Windows.Forms.MessageBox.Show(str(ex))

def StateChange(self, obj, args, name, typ):
    self.name = name
    self.typ = typ
    ghenv.Component.ExpireSolution(True)

You can use cpickle

1 Like

Shelve is another another simple option with python

1 Like

Thanks for your suggestion do you know any good example of this?

I am unsure of how the native components manage to keep persistance (eg the maintain/renumber switch in the select branch component) and if the method used there can be replicated in gh python.

TBH, I have never used cpickle with ghpython, or rhino python for that matter. Haven’t had a case.

A quick search lead me to this page that has a good example you can adapt it to your case:
https://wiki.python.org/moin/UsingPickle

1 Like

Seems like one viable way to go and will probably resort to it.

I am now using an input to where I stick the menu selection to Persistent Data and recall Persistent Data using the following method:

class MyComponent(component):
    def __init__(self):
        self.Component = ghenv.Component
        pp = self.Component.Params.Input[3] 
        try:
            self.typ = pp.PersistentData[0][0].Value #Gets internal Value
        except:
            self.typ = 0

    """
    def RunScript()......
    """

    #Edited StateChange to store Persistent Data
    def StateChange(self, obj, args, typ):
        #Create or modify the Persistent Data
        pp = self.Component.Params.Input[3]
        pp.PersistentData.ClearData()
        pp.PersistentData.Append(gh.Types.GH_Integer(typ))
        self.typ = typ
        ghenv.Component.ExpireSolution(True)

This works well, however I wish to remove to hide the input so the user uses the internal menu to change the state of the component. Is there a way to store persistent data to some internal param, rather then then using an input for it?

Found this thread regarding a similar issue, it looks like read()/write() methods are the way to go. @piac

You can use scriptsyntax.sticky

This is a global dictionary that can hold any type of data and transfer it between RhinoPython and GhPython. Use it like any other dictionary

problem with this one is, it won’t hold the data between sessions, you may have to save to a file (or serialize with pickle) then at new session look for the file and put them in the sticky dictionary. Respectively think of a procedure to serialize before closing the session.

Important note: when using sticky make sure to use unique key names. So that it doesn’t conflict with other scripts using it. Best practice is to get the uuid of the ghpython component and use it as prefix or suffix for your keys

2 Likes