Getting Property groups as dictionaries

I recent­ly reworked Mirage’s live mode to be more effi­cient. One of the things I want­ed to improve was detect­ing changes in ter­rain set­tings. I fig­ured the best way to do it was get­ting a dic­tio­nary of the set­tings and find­ing what changed in it.

So I wrote a lit­tle func­tion to get all the prop­er­ties inside a PropertyGroup as a dic­tio­nary. I fig­ure this could be use­ful for every­one, so here it is.

# Don't forget:
from typing import Dict
from bpy.types import PropertyGroup

def group_as_dict(group: PropertyGroup) -> Dict:
    """Get values from a property group as a dict."""

    EXCLUDE = {'a_prop_I_dont_want', 'another'}
    prop_dict = {}

    for key in group.__annotations__.keys():

        # Avoid properties we don't want
        if key in EXCLUDE:

        # Each item in __annotations__ is a tuple 
        # containing the type and a dictionary
        prop_type = group.__annotations__[key][0]

        # Pointers to other property groups
        if prop_type == PointerProperty:
            prop_dict[key] = group_as_dict(getattr(settings, key))

        # Store collection properties as lists
        elif prop_type == CollectionProperty:
            prop_dict[key] = [group_as_dict(i) 
                              for i in getattr(settings, key)]

        # BUG? IntVectorProperties don't return the Vector value on
        # getattr(). Looks like we have to get it ourselves for now.
        elif prop_type == IntVectorProperty:
            prop_dict[key] = [i for i in getattr(settings, key)]

        # Get everything else as a value
            prop_dict[key] = getattr(settings, key)

    return prop_dict

This func­tion is recur­sive. It will take nest­ed PropertyGroups as well as CollectionProperties, which are returned as lists. I also added a fix for IntVectorProperties, where getattr() returns the point­er instead of the actu­al val­ues. You could also copy that line and extend it to the oth­er vec­tor prop­er­ties. Depending on what you would like to do with this dict, you might want a tuple or list of val­ues instead of a Vector object.

You can also exclude prop­er­ties by adding their names to the exclude set. This is great for UI prop­er­ties that you don’t want to store, like using enums for tabs.

Did you find it use­ful? Let me know in the com­ments!

All the posts you can read
TutorialsBlender, Python22.04.2020


  1. aditiavfx(10 months ago)

    You just save my day…thank you.

    1. Diego Gangl(10 months ago)

      Glad to hear!

  2. Rombout Versluijs(8 months ago)

    Do you have per­haps info where i should look for get­ting into PropertyGroups and PointerProperty. I want to add this to a cou­ple adds im doing. Im real­ly con­fused of the cor­rect approach to this

    1. Diego Gangl(8 months ago)

      The best place to start is the API docs:
      Basically cre­ate a prop­er­ty­group with all your props in it. Then reg­is­ter the class, and make a PointerProperty in bpy.types.Scene or bpy.types.Object to hold it (for exam­ple).

  3. Lisa(3 weeks ago)

    Thanks for that, it was real­ly help­ful. I just had to change some­thing because a PointerProperty isn’t nec­es­sar­i­ly anoth­er prop­er­ty group.

    I changed the con­di­tion to
    if prop_type == bpy.props.PointerProperty:
    if isinstance(getattr(group, key), bpy.types.PropertyGroup):
    prop_dict[key] = group_as_dict(getattr(group, key))
    prop_dict[key] = getattr(group, key).name

    Of course it would be pos­si­ble to also some­how make any object into a dic­tio­nary but that real­ly depends on what you use it for. This is most like­ly some­thing you would put in the exclude.

Leave a Reply

Your email address will not be published.