Storing values for later

How are you supposed to store variables when writing an addon, so that they can be read/written to at any time during the Blender session (ie. held in memory until blender is closed)? It seems like you would need to put them in some sort of class with a bl_idname, is that right?

You create a Property and attach it to something you can access whereever you need it, e.g. the scene.
https://www.blender.org/api/blender_python_api_2_66_4/bpy.props.html

I like to use a string properties(obviously don’t draw it in addon UI) and store information.

Depends on which level you want to use them, if it’s per object you can define a properly like this:


bpy.types.Object.PersistentData = bpy.props.StringProperty()

Then you can store your data as some format (I like json) and parse it later


bpy.context.active_object.PersistentData = '{radius: 10, size: 15}'

If it’s even lower resolution, like faces of vertices, I’d advice layers



import bmesh

mesh = bmesh.new()
mesh.from_mesh(bpy.context.active_object.data)

ll = mesh.faces.layers.int.new()
mesh.faces[100][ll] = 15

mesh.to_mesh(bpy.context.active_object.data)


This also will be saved in blend file and can be accessed any time via bmesh.

Thanks for the help guys! :slight_smile:

Attaching values / groups of values to parts of the app/scene still seems so strange to me. I know that at least in Max/Maxscript and Maya/MEL variables are local to the script they were created in and don’t need to be assigned to anything else (even globals just ‘exist’ in memory, and the user doesn’t need to care where they are stored). But I’m sure there’s various reasons why the Blender devs decided to implement it like that. Well, I was able to get things running fine, so it’s all good either way.

I did however run into an issue with FloatProperties; For some reason when I assign a default value and later print it it returns a slightly changed value. Like I assign a default value of 22.2 , assign the PropertyGroup it’s in to the scene via a PointerProperty, and then print the value it comes back as 22.200000762939453
Any idea why this happens?

That’s basic programming knowledge.
Some floating point numbers have a periodic binary equivalent.
22.2 for example is 10110.001100110011001100110011001100110011001100110011… as binary. Note the periodic “0011”.
It’s similar to how 1/3 in the decimal system is 0.33333333… as decimal floating point number.
So there is just no way you can store an exact “22.2” in a computer.

There seems to be a misconception among many Blender Python coders, about the use of custom properties. Custom properties are to be used when you actually want to associate data with certain ID type (e.g. Scene, Object, etc.).

Note that there are two kinds of “custom properties”, each with its own uses. The kind that was previously mentioned in this thread, is an RNA property, and it has to be bound to an ID type, before you can store data in it. This kind of property will have an instance available on any data block of the type it was bound to, and if no value has been set to the property on that specific data block, it will carry a default value (which you can optionally set at declaration time). This kind of property also allows you to define useful functions like get, set, etc. The down side is that you are limited in the way of what kind of data you can store. (More on RNA properties here)

The other kind of property is the ID property. This one is stored on a per data block basis, and is not associated with specific ID types. All data blocks in Blender that are derived from the ID class (which is almost anything you’ll want to use anyway), will support ID property assignment. The best part of these is that the ID derived data blocks work just like standard Python dictionaries, in the way you assign and retrieve your properties. Also, ID properties can store any data, though they have a “preference” for int, float, and string types, so anything that can be cast into one of those types, will (e.g. a bool would become an int). All other types of data (like dicts, lists, custom types, etc.), will be stored as a memory pointer to that data, but can be accessed normally.

More on RNA vs ID properties here (Article is slightly wrong in saying ID properties only store specific types).

Now, one thing those custom properties are not intended for, is storing session data. There are many reasons why that’s a bad idea, here are a few:

  • They have to be associated with some existing data block, so when people want to store global data they usually store it in the scene, however if the user changes to another scene, your data is no longer available in the current scene (you still can access the other scene, but that is just ugly). Even worse, if your data has to be preserved across file loads, you’re out of luck, as there is just no way with custom properties.
  • It is slow, as Blender will do some checks on your data, that you simply don’t want, when you just want to store raw Python objects. So if you have a lot of data to store/retrieve, it can take a long time to manipulate that data.
  • Properties are saved in .blend files, so if you just want to use the variables in your session, they will unnecessarily be saved with the file.

As for what you actually DO want to do, is just use global variables. Normal Python global variables declared in your addon module, will be accessible to you from the moment your addon is registered, until blender is closed (even if the addon is unregistered and re-registered, and even if new files are loaded). I would personally recommend that you use just one global variable of “dictionary” type, so you don’t have to clutter your whole code with a bunch of “global” definitions (you won’t even have to use one, as global variable access is implicit in Python, unlike global variable writing, and if you declare your dict variable on your code’s top level, you will never have to write to the variable itself, only to its members.)

One note, is that if you want your global variable to be reset on new file loads, you can use a “load” handler for that (more here).

And finally, if you are in any state of sanity, do NOT EVER use json or any string format to store data in memory! I can not even imagine the kind of performance you would get every time you had to write of retrieve some data. Please people, text based formats are strictly for long term storage, you just don’t store structured text in ram while you’re using the data. If you see yourself in a situation where you need to do that, there is most likely something very wrong, and you’re probably overlooking a better way to do it.

Anyway, I hope that helped :slight_smile:

2 Likes

I understand what you’re saying but until now I’d never actually run into this issue using Maxscript or MEL script. I also just tried storing 22.2 in a variable and then printing the variable in C++ (using codeblocks) and it returned the correct number too.

Seeing as they don’t show this issue, there must be a way around it?

They probably do some kind of rounding or check with a small epsilon for cases like this.
It depends on the print function I guess.
For example, this is 22.2 printed once with printf() and once with cout in C++:

Attachments