¿Cómo verificar si la propiedad del nodo no es Ninguna mientras se itera a través de los materiales?
Me encuentro con un error sin atributo al iterar a través de nodos y grupos de nodos en algunos archivos combinados.
Error: AttributeError: el objeto 'NoneType' no tiene atributo 'name'
¿Cómo verificaría si los objetos no tienen la propiedad 'nombre' y lo omitiría?
for mat in bpy.data.materials:
if mat.use_nodes == True:
for node in mat.node_tree.nodes:
#check if no has attribute name
if node.type in ["GROUP"] and node.node_tree.name == 'NodeGroupName':
Respuestas
Un atributo puede serNone
El error NoneType has no attribute
es un error común que se ve en las secuencias de comandos de Blender. Por ejemplo puede darse el caso de quecontext.object is None
Al OP recomendaría editar el título de la pregunta para reflejar más este mensaje de error.
Error: AttributeError: 'NoneType' object has no attribute 'name'
lanzado por node.node_tree.name == 'NodeGroupName'
está informando node.node_tree
tiene el valor None
. Puede probar que este sea el caso, es decir
if node.node_tree is None:
Opuesto a
if hasattr(node, "node_tree"):
Ambos serán verdaderos cuando el árbol de nodos seaNone
En realidad, es un caso extraño que el código en cuestión arroje este error, ya que no sé (todavía) cómo agregar un nodo de grupo y no tengo un nodo_árbol vinculado. Especule que esto es el resultado de eliminar un grupo de nodos bpy.data.node_groups
que era un nodo de un árbol de nodos materiales.
por lo tanto, la última línea del guión de preguntas podría ser
if (node.type in ["GROUP"]
and node.node_tree
and node.node_tree.name == 'NodeGroupName'
):
ya que encadenar ands cesa en primer lugarFalse
Usandogetattr
Dado que prácticamente trataríamos de la misma manera usando el atributo get con el tercer argumento predeterminado
node_tree = getattr(node, "node_tree", None)
será None
en ambos casos. En mi opinión, esto "triunfa" usando tanto el árbol de nodos como la prueba de atributo de nombre. None
no tiene nada, si sabemos que no es ninguno, parecería superfluo seguir probando los atributos . También podemos asegurar que si un árbol de nodos no None
lo es, tendrá un nombre .bpy.types.ShaderNodeTree.name
Guión de prueba
Usando lo anterior con la "doble prueba" para que un nodo sea de 'GROUP'
tipo, verifique que no tenga un árbol de nodos.
Haga un diccionario, con claves que coincidan con el nombre del grupo de nodos que contenga una lista de nombres de materiales, tuplas de nombres de nodos.
import bpy
from bpy import data
from collections import defaultdict
# all the group nodes in blendfile
print(data.node_groups.keys())
group_nodes = defaultdict(list)
# create a look up dictionary
for m in data.materials:
if m.use_nodes:
for n in m.node_tree.nodes:
nt = getattr(n, "node_tree", None)
if nt and n.type == 'GROUP':
group_nodes[nt.name].append((m.name, n.name))
print(group_nodes)
Producción.
Archivo con 1 grupo de nodos "Test_Material", 2 materiales "TestMat" y "TestMat.001".
El grupo de nodos se utiliza en ambos materiales con el nombre "Grupo" en ambos.
['Test_Material']
defaultdict(<class 'list'>, {'Test_Material': [('TestMat', 'Group'), ('TestMat.001', 'Group')]})
Notas:
Cuidado con equiparar True
o False
en pruebas. Por defecto, Python equipara la mayoría de los tipos con True o false. Algunos ejemplos de false son None
, el entero 0
y una lista vacía[]
Métodos como hasattr
return True
o bienFalse
if hasattr(foo, "bar") == True:
si foo.bar
existe esto se lee algo parecido a
if True == True:
en su lugar, simplemente use
if hasattr(foo, "bar"):
Cambiar ligeramente lo anterior para devolver boolean false en lugar de none cuando el nodo no tiene el atributo node_tree, if nt:
será falso en ambos casos, pero podemos discernir entre los dos.
nt = getattr(n, "node_tree", False)
if nt and n.type == 'GROUP':
group_nodes[nt.name].append((m.name, n.name))
if nt is None:
print(f"{m.name}:{n.name} node_tree is None")
Basado en el comentario de Ron Jensens:
for mat in bpy.data.materials:
if mat.use_nodes == True:
for node in mat.node_tree.nodes:
if hasattr(node, 'node_tree') == True:
if hasattr(node.node_tree, 'name') == True:
if node.type in ["GROUP"] and node.node_tree.name == 'NodeGroupName':