Name Error name xxx is not defined

Hello,
I’am an absolut beginner in programming in python and blender and this is my first python script for blender.
The script rounds the selected vertices local positions.
After starting the script and pressing the “Round”-Button I get following error message:

psutil available
Digits:
2
<bpy_struct, Scene(“Scene”)>
Traceback (most recent call last):
File “/Text”, line 46, in execute
NameError: name ‘round_vertices’ is not defined

location: :-1

location: :-1
Error: Traceback (most recent call last):
File “/Text”, line 46, in execute
NameError: name ‘round_vertices’ is not defined

location: :-1

The script:

> import bpy
> import bmesh
> 
> class OBJECT_PT_vertex_rounder(bpy.types.Panel):
>     bl_label = "Round Vertex Positions"
>     bl_space_type = "PROPERTIES"
>     bl_region_type = "WINDOW"
> #   bl_context_type = "mesh_edit"
>     bl_context_type = "object"
>     
>     
>     def draw(self, context):
>         layout = self.layout
>         scn = bpy.context.scene
>         obj = context.object
>         
>         layout.prop(scn,"digits")
>         
>         layout.operator("vertex_rounder.draw_op")
>         
>         
> class vertex_rounder_draw_operator(bpy.types.Operator):
>     bl_idname = "vertex_rounder.draw_op"
>     bl_label = "Round"
>     
>     def round_vertices(digits = 2):
>        obj=bpy.context.object
>        if obj.mode == 'EDIT':
>            bm=bmesh.from_edit_mesh(obj.data)
>            for v in bm.verts:
>                if v.select:
>                    locale_co=v.co             
>                    v1 = round(locale_co[0],digits)
>                    v2 = round(locale_co[1],digits)
>                    v3 = round(locale_co[2],digits)
>                    v.co=[v1,v2,v3]
>            
>     
>     
>     def execute(self,context):
>         scn = bpy.context.scene
>         
>         print("Digits: ")
>         print(scn.digits)
>         print(bpy.context.scene)
>         round_vertices(scn.digits) # Here is the problem !!! Until here,python is doing it's work !
>         return {'FINISHED'}
>   
>         
>     
>     
>        
> 
>     
> 
>      
> def register():
>     bpy.utils.register_class(OBJECT_PT_vertex_rounder)
>     bpy.utils.register_class(vertex_rounder_draw_operator)
>     
> def unregister():
>     bpy.utils.unregister_class(OBJECT_PT_vertex_rounder)
>     bpy.utils.unregister_class(vertex_rounder_draw_operator)
>     
> if __name__ == "__main__":
>     bpy.types.Scene.digits = bpy.props.IntProperty(name="digits",default=2,description ="digit limit for rounding")
>     register()

It seems that python doesn’t find the declaration of the round_vertices(digits = 2)-method.

But how can that be ?
The indentation seems to be correct.
python builds apparently an instance of vertex_rounder_draw_operator(bpy.types.Operator) because it is setting bl_label variable.

If I move the round_vertices method into the execute method like this:

 > def execute(self,context):
>         scn = bpy.context.scene
>         #Aufruf
>         print("Digits: ")
>         print(scn.digits)
>         print(bpy.context.scene)
>     
>         obj=bpy.context.object
>         if obj.mode == 'EDIT': # Here is the problem !
>            bm=bmesh.from_edit_mesh(obj.data)
>            for v in bm.verts:
>                if v.select:
>                    locale_co=v.co
>                    v1 = round(locale_co[0],scn.digits)
>                    v2 = round(locale_co[1],scn.digits)
>                    v3 = round(locale_co[2],scn.digits)
>                    v.co=[v1,v2,v3]
>         
>         
>         
>         
>         return {'FINISHED'}

I get this error message:

psutil available
Digits:
2
<bpy_struct, Scene(“Scene”)>
Traceback (most recent call last):
File “/Text”, line 31, in execute
AttributeError: ‘NoneType’ object has no attribute ‘mode’

location: :-1

location: :-1
Error: Traceback (most recent call last):
File “/Text”, line 31, in execute
AttributeError: ‘NoneType’ object has no attribute ‘mode’

location: :-1

So I guess there is a problem with the namespaces which I can’t comprehend.

Second question:
How can I position the panel to a postion which makes more sense ?

Thank you for reading. I hope you can help me.

Hi!

Please wrap the code using 3 backticks to make code blocks with proper indentation:

```
(code)
```

Why it reports a NameError

Methods by design do not share execution scope (which you assume to be the class scope). Your execute doesn’t see your “neighboring” round_vertices. There are ways of getting around this paradigm, but that’s irrelevant here. So, python looks in the local scope, finds nothing, goes up to global scope, finds nothing, then throws a NameError.

How to access neighbor methods?

Use the self argument.

Instance methods, methods that take a special self first argument like can access your round_vertices by calling self.round_vertices().

There’s one little caveat, your round_vertices declaration must use self as the first parameter:

    def round_vertices(self, digits = 2):  # Class function? "self" always first.
        ...

But why use self at all, you might ask. And you’re right, you don’t need instance methods. Define them in the global scope and they become first-class objects and are no longer methods but regular functions.

AttributeError: ‘NoneType’ object has no attribute …

Python is telling you that bpy.context.object is None. You can:

  1. Make the operator fail, with a warning.
  2. Find the object in a different way.

Thank you very much. :grinning:
The problem seems to be solved.

The declaration of self and that you declares the parameter but not hand over it in the function-call is very strange compared to other programming languages.

1 Like

I agree it takes some getting used to.
The definition of a bound method is that one or more arguments are passed implcitly.

self.function(arg)

is synonymous to:

MyClass.function(self, arg)

but with the benefit of having a faster lookup.