How to store data between sessions for python plugin

Hi there,

I have a python script, which I like to remember some data between calls to that script, but also between sessions.

Well, to remember data between calls there is an easy solution as I could use the scriptcontext.sticky dictionary as in this sample. This is a standard python dictionary and as such very versatile to use. However, this is not stored between sessions

To store values between sessions the only possibility (besides writing to a separate file) is to use the DocumentUserData with rhinoscriptsyntax or RhinoCommon. This has two drawbacks. I am limited to storing string variables in only one layer of nesting (section, entry, value) and I have to write to the DocumentUserData all the time as there is no proceedure that automatically stores to the DocumentUserData if Rhino is being closed.

Apparently, the best way to achieve an automated storage between sessions would be via a Plug-In and the overridden readDocument() and writeDocument() Methods. However, as I understand, this will currently not work with a Rhino Plug-In.

Are there any alternative ways to store data between sessions I am not aware of?

Or is there a possibility to mix C# and Python for a Plug-In, e.g. use C# as a wrapper for an otherwise Python based Plug-In? If so, are there any tutorials or samples?

Any help is very much appreciated!

Thanks
Juryk

Have you considered storing it in a text file? It’s quite easy to do and you can save it next to the rhino file or a dedicated location.

Thanks for the comment!

Yes, I did and I see three disadvantages. First I have an external file I might have to manage, e.g. copy it together with my actual 3dm-file. Secondly, I still would have to read and write at every call, since I can’t be sure the document is not closed before the next call. And lastly I have an comparatively expensive file IO operation twice in call. Although, the effort may still be neglectable.

I was hoping for a better solution and the Plug-In user data seems to do the trick. Writing a text file may be the easier solution, though.

Cheers

Juryk

1 Like

Hi @juryk.henrichs, data stored in the sticky.dictionary does survive when closing and opening new documents under windows.

To store your data into something persistent when Rhino is closed, i would suggest to use pythons ConfigParser or SafeConfigParser modules and save your values in an *.ini file at your script or compiled plugin location. I guess the best way would be to combine scriptcontext.sticky with the ConfigParser and write the data when the RhinoApp.Closing event or RhinoDoc.CloseDocument event is fired. So you would have to subscribe to the event.
_
c.

You should be able to serialize and deserialize arbitrary python objects into string format using the pickle module (pickle.dumps and pickle.loads), or using json if the objects are simple number/string/list/dict literals.

Hi Clement,

thanks. I was not aware of the RhinoApp and RhinoDoc events. This way I have to read and write data only ones in a rhino session.
I found this example here to get me started. Is there any better example or a more commented documentation as in the RhinoCommon SDK?

I also still don’t like the idea of having a separate file for the extra data. Especially since this is linked to the context of the respective document.

I wonder if I could actual use the Rhino.Colletions.ArchivableDictonary and Rhino.FileIO.BinaryArchiveWriter Classes to write the data while subscribing to RhinoDoc.BeginSaveDocument event. Would this be possible?

Juryk

Hi @juryk.henrichs,

the event example you’ve linked to is what i used in the past. There is not much to add, only that you really need to store the event into your sticky, otherwise programming events with python gets confusing. Always turn the event off when adding new code to the delegate function. Then turn it on to try it. Note that the delegate the event calls will not fire any errors. You need to keep track of them using a try / except block.

I’ve used the ArchivableDictionary with python once, it required a class instance of

Rhino.DocObjects.Custom.UserDictionary

from which i was able to retrieve the Dictionary in which i’ve stored geometry, strings etc. Writing to a new 3dm file worked ok with BinaryArchiveWriter, reading back with the BinaryArchiveReader.

I guess you could also write to your default template but i have not done this yet.

You could store in the registry, but thats rather risky and limited compared to above.
_
c.

1 Like

Hi @clement

I have a relevant question for you since you seem to have used BinaryArchiveWriter in Python.
I’m trying to get some geometry out of rhino without saving the file and this has to be a serialized format, Either string or binary and I think BinaryArchiveWriter could work.
I just can’t seem to figure out how to instantiate that class.
here’s what I have so far:

plane = Rhino.Geometry.Plane.WorldXY
circle = Rhino.Geometry.Circle(plane,10)
UD = Rhino.DocObjects.Custom.UserDictionary()
AD = Rhino.Collections.ArchivableDictionary(UD)
AD.Set("circle", circle)
Rhino.FileIO.BinaryArchiveWriter.WriteDictionary(AD)

Last line gives me an error. Do you have a basic example of how to use the Rhino.FileIO.BinaryArchiveWriter?

Thanks a lot

Hi @mkarimi,

sorry i do not have a working example at hand, but i think that the BinaryArchiveWriter has no public constructor, so you must get it from a Rhino.FileIO.BinaryArchiveFile which you can get if you provide a filename and BinaryArchiveMode. But be very careful with this as you can easily destroy an existing Rhino file while writing to it from “outside”.

btw. this does not work as far as i know:

AD.Set("circle", circle)

You must provde a GeometryBase to store into ArchivableDictionary, eg. convert the circle to a curve using:

AD.Set("MyCircleCurve", circle.ToNurbsCurve())

If not Rhino will just return True when you query AD.Item["circle"]

btw. i’ve asked for easier saving / reading of typed data some years ago. It has been scheduled for “future”:

https://mcneel.myjetbrains.com/youtrack/issue/RH-54753

_
c.

1 Like

Thank you @clement
I give Rhino.FileIO.BinaryArchiveFile a try, Onriginally I thought with the BinaryArchiveWriter I need to make a class with a constructor and inherit BinaryArchiveWriter. But that wasn’t the case.