Python and Geo Nodes: Trying to access instance attributes: DepsgraphObjectInstance invalid

(EDIT: Updating the code and output to be more clear about the problem)

Hi,

I am trying to access the attributes of the instances created by a Geo Nodes modifier. I am reasonably proficient in Python, but an absolute newbie to coding for Blender. I have included my sample blend file in case anyone needs it, but it is super basic.

I have looked at this post: Accessing Evaled Object Instance Attribute from Geometry Nodes

I have also looked at the posts it references as well as this page: https://docs.blender.org/api/current/bpy.types.Depsgraph.html

But I am still lost.

Here is my code:

import bpy

depsgraph = bpy.context.evaluated_depsgraph_get()
obj = bpy.data.objects["Cube"]
eval_obj = obj.evaluated_get(depsgraph)

instances = [inst for inst in depsgraph.object_instances if inst.is_instance and inst.parent is eval_obj]
for instance in instances:
    print(instance)

This is run on the default cube object with a geometry nodes modifier that instances a cube on each point of the default cube. Very basic.

The output of the above code is:

<bpy_struct, DepsgraphObjectInstance invalid>
<bpy_struct, DepsgraphObjectInstance invalid>
<bpy_struct, DepsgraphObjectInstance invalid>
<bpy_struct, DepsgraphObjectInstance invalid>
<bpy_struct, DepsgraphObjectInstance invalid>
<bpy_struct, DepsgraphObjectInstance invalid>
<bpy_struct, DepsgraphObjectInstance invalid>
<bpy_struct, DepsgraphObjectInstance invalid>

I can see that it has found all eight instances, but somehow I am still missing a step when trying to access any info about these instances. Somehow they seem to not really exist? Not sure how to interpret “<bpy_struct, DepsgraphObjectInstance invalid>”. What additional (or changed) code would I need to access, say, the position or rotation or name of each of these instances?

Any guidance much appreciated!
instance_python_eval_test_v001.blend (936.6 KB)

Ok, I have some more info, but I am not sure why this is the case.

If I change the list comprehension into a generator, then suddenly the code works.

But most of the examples that I saw listed here and on stack exchange use list comprehension. Has something changed since those examples were written? Or am I completely misunderstanding how they worked?

The following code works. Note that the only change is to switch the list comprehension to be a generator. I would love to know why that is the case.

(Now I still need to get the data from the instances, but I think that that is a solvable issue for me - though if anyone wants to gently push me along I would not be mad :slight_smile: )

import bpy

depsgraph = bpy.context.evaluated_depsgraph_get()
obj = bpy.data.objects["Cube"]
eval_obj = obj.evaluated_get(depsgraph)

instances = (inst for inst in depsgraph.object_instances if inst.is_instance and inst.parent is eval_obj)
for instance in instances:
    print(instance)

and here is its output:

<bpy_struct, DepsgraphObjectInstance at 0x294813240>
<bpy_struct, DepsgraphObjectInstance at 0x294813220>
<bpy_struct, DepsgraphObjectInstance at 0x294813240>
<bpy_struct, DepsgraphObjectInstance at 0x294813220>
<bpy_struct, DepsgraphObjectInstance at 0x294813240>
<bpy_struct, DepsgraphObjectInstance at 0x294813220>
<bpy_struct, DepsgraphObjectInstance at 0x294813240>
<bpy_struct, DepsgraphObjectInstance at 0x294813220>

Hmm… no cant say much on the why, I wouldnt have expected this behaviour. Maybe its best to ask it over at devtalk or report it as a bug to get their opinion on it. Let me know what they said. Would be interested in it aswell.

But here’s a gentle push.

import bpy

depsgraph = bpy.context.evaluated_depsgraph_get()
obj = bpy.data.objects["Cube"]
eval_obj = obj.evaluated_get(depsgraph)

instances = (inst for inst in depsgraph.object_instances if inst.is_instance and inst.parent is eval_obj)
for instance in instances:
    #print("mw",instance.matrix_world)
    loc, rot, scale = instance.matrix_world.decompose()
    print(loc, rot, scale)

Thanks for the gentle push :slight_smile:

I am trying to post over on devtalk, but I don’t have the proper permissions. When I asked where I should post, they suggested that I do it here. So I will make a new post here about the issue and maybe someone can enlighten me as to whether this is expected behavior or a bug.

I’ll edit this post with a link to the new post once it is up.

EDIT: here is the link to the new post

Thanks again!

Well no, dont open new threads with the same problem. Its just allowed to open one thread per topic here.

You got an answer over there on devtalk by a user no dev, overall you are hurrying to much They might simply answer later. Also they typically prefer it as bug reports. So no matter what, simply post it as a bug. It will be triaged then, this might very well be one so its just fine to do so. There are some differences if its now list comprehension or a generator expression but that shouldnt really break it here.

Anyway delete the other thread and update this one, you can normally edit a threads title of your own threads. If you are too new and your status doesnt allow it just ask, I can do it for you.
Good luck.

Got it. Thanks.

I would delete the other post, but now there is a reply there. Should I still delete it?

I’ll update the thread title here, and then post the behavior as a possible bug. The reason I didn’t do so immediately is just that I don’t know enough about Blender python to know whether it is actually a bug or not. I.e. I have never seen it working as a list comprehension myself, only examples of that posted elsewhere. For all I know, it might always have only been possible using a generator.

But I can certainly post it as a bug. It makes sense to let them triage it like you said. Thanks for your input.

1 Like

I’m no moderator, so let joseph have a look , if its best to merge the two threads or do something else. Can you have look @joseph, thanks.

Yeah as I said I am also not sure if they will accept it as bug. Its partially dependent on their existing code. So even if not you get the answer you’re looking for and the next one with the same problem will find your thread instead.

So, good luck. :smiley:

Thanks so much for your help!

1 Like

It’s not a bug as it’s documented - https://docs.blender.org/api/current/bpy.types.Depsgraph.html#bpy.types.Depsgraph.object_instances

object_intstances - All object instances to display or render (Warning: Only use this as an iterator, never as a sequence, and do not keep any references to its items)

So make sure you get everything you want from the object instance during the loop and don’t access it (or it’s attributes, such as matrix_world) outside the loop, otherwise you’ll get this kind of errors or Blender might even crash.

Example you attached is using a list just to get it’s length, it never accesses list elements, therefore no issues.

This is so very helpful, thanks!

I could not imagine that it would have been a bug, and your explanation is very clear and explains it perfectly. And now that I go back and look at the examples they are doing exactly what you say.

I am currently learning some more about Blender python programming, so hopefully my understanding of the Depsgraph and how it is used will improve.

Thanks again.