Building NodeGroups with Python crashes blender

Hey all. I’ve been working on a script which stores materials, including NodeGroups, to a json block, and then rebuilds the materials, in order to smooth the transition between departments. I posted a bug report which has now been closed, but the script still crashes Blender; the problem seems to be specifically related to creating Links to ‘Group Input’ and ‘Group Output’ nodes - every time I’ve crashed Blender, the log indicates that it was in the attempt to link something to either one or the other in a NodeGroup. I will refer to Input Sockets for the rest of this post, but it appears to apply to Outputs as well.

Group Inputs and Outputs use a “virtual” socket in the UI, which the user simply treats like any other socket, and it fills in the appropriate name after they create the link in the GUI. There is some ambiguity as to how one should handle this linking operation in Python:

I’ve been interacting with @LazyDodo and @JesterKing about this in blender.chat, and Mr. Dodo provided me with this script which presumably demonstrates the correct method, specifically using the Node.inputs.new() method to assign an input with the appropriate name and identifier. However, when I attempt this method in the Python console, no socket is created as of yesterday’s build of Blender (I compiled a debug version and looked at the call stack but C is still an ambition of mine, rather than a skill - both of the aforementioned gents have indicated they will have a look in due course, as the crashing is still a fact at this point).

Conversely, if I just go ahead and create the link in the Python console to the Group Input using the virtual socket’s index, skipping the formal creation of the Socket, it works just fine, assigning the right name and all.

Either way, though, once I run the script using either method, with many such linking operations, it will inevitably crash before it gets through the entire JSON block, but it appears to be random when it will happen - it doesn’t crash immediately on the first go.

I’ve also observed behavior where the script stops due to some error or other but does not crash blender, but when I then went and attempted to create a link in the Console, Blender crashed then. It’s as if a buffer is getting overfilled, maybe, or memory blocks are failing to be handled. I noticed the code which crashes is C, so there would be no garbage collection going on. I’m flailing in the dark when I talk C, though.

I filed a bug report earlier this week, as I said - it’s now been closed, but as I said, the crashing continues; anyone who would like to see it happen, or have a look at that call stack themselves, can collect a piece of script and a JSON block from the Google Drive link in the bug report above.

Note that there was early speculation that the script’s use of negative indices might be the cause of the crash due to C/C++ not liking them, but I have many logs indicating a crash even when using a 0 or positive index.

It is also worth noting, for the benefit of other hapless Pythonites that when you use the inputs.find() method to retrieve an index, the method will return -1 if the node or socket is not found; I misinterpreted that return as indicating the last socket of the set. That error is still present in the script linked to in the bug report (note that LazyDodo’s script catches that), however, I have logs which report crashing even when indexes are not negative, so it would appear that running that script on the included JSON block is a quick and convenient way to bring on the relevant crash.

The scripts is gave you, are part of an addon called bricktricks, somehow i had some issues yesterday over remote desktop, but when run from the actual computer all seems fine.

I’d start by installing the addon, and see if it works, if it does and you have known working good code, steal the bits and pieces you need :slight_smile:

I just installed your add-on, and it does appear to work, though your groups appear to be non-standard groups; I can’t TAB into them to verify the links. Blender does not crash, or do much really, when a link fails.

Whatever the case, you can see that outputs.new() is not working in a very straightforward way; I just loaded up and did what’s below in the console. The method is broken:

D.node_groups.new('testgroup', 'ShaderNodeTree')
bpy.data.node_groups['testgroup']
D.node_groups['testgroup'].nodes.new('NodeGroupInput')
bpy.data...nodes["Group Input"]
D.node_groups['testgroup'].nodes['Group Input'].outputs.new('VALUE', 'TestSocket', identifier='Output_1')
bpy.data.node_groups['testgroup']...NodeSocket
for out in D.node_groups['testgroup'].nodes['Group Input'].outputs:
...     print(out.name)
...     


>>> 
for out in D.node_groups['testgroup'].nodes['Group Input'].outputs:
...     print(out)
...     
<bpy_struct, NodeSocketVirtual("")>

>>> 

No socket created.

it is making nodegroups in the background, the UI is custom on top of that, once you add a node from the brick tricks section of the add menu, the backing group becomes available in the Group menu, that being said, these groups were not designed for manual editing, so all nodes are pretty much left at their default location (0,0) which makes tabbing into them to see what’s going on… unpleasant…

Ahh, I can see the nodetrees there, yes. Sorry if I’m being tiresome, I’ve been stuck at this crash for a few days now and I’m not impressing my coworkers. :>

I think I just figured out my problem… (socket type)

Further info: Rather than just running the .new() method, I assigned it to a variable with sock = at the front.

The socket does get created, as I can do things like sock.name and sock.identifier, and it returns the proper responses. However, the socket does not appear on the Group Input node. Perhaps there’s another step that I missed…

I’m unsure why you are struggling this much, you have working code, best i can do is show you how to make the simplest nodgroup possible, single group linking input to output:

import bpy
tree = bpy.data.node_groups.new('MyGroup', 'ShaderNodeTree')
output = tree.nodes.new('NodeGroupOutput') 
output.name = 'g_output'
input = tree.nodes.new('NodeGroupInput') 
input.name = 'g_input'
tree.outputs.new('NodeSocketFloat', 'Out1') 
tree.inputs.new('NodeSocketFloat', 'In1') 
SocketOut = tree.path_resolve('nodes["g_input"].outputs[0]')
SocketIn = tree.path_resolve('nodes["g_output"].inputs[0]')
tree.links.new(SocketIn,SocketOut)
1 Like

Well, that’s incontrovertible proof that it can be done; I’m gonna rewrite my function with this as the starting point. I also don’t know how this got so hard, but I am still new at this, in the final analysis.

Some days are bright and full of victory, others are just incomprehensible. I’m closer to the latter today. :>