what causes AttributeError?


AttributeError is raised when I use a name that is NOT in an object.


what is an attribute?

An attribute is a name for something that belongs to an object, for example, a human being has attributes like height, weight, sex and color, they are also known as properties.


preview

These are the tests I have by the end of the chapter

 1import src.attribute_error
 2import unittest
 3
 4
 5class TestAttributeError(unittest.TestCase):
 6
 7    def test_attribute_error_w_variables(self):
 8        src.attribute_error.variable_00
 9        src.attribute_error.variable_01
10        src.attribute_error.variable_02
11        src.attribute_error.variable_03
12
13    def test_attribute_error_w_functions(self):
14        src.attribute_error.function_00()
15        src.attribute_error.function_01()
16        src.attribute_error.function_02()
17        src.attribute_error.function_03()
18
19    def test_attribute_error_w_class_attributes(self):
20        src.attribute_error.AClass.attribute_00
21        src.attribute_error.AClass.attribute_01
22        src.attribute_error.AClass.attribute_02
23        src.attribute_error.AClass.attribute_03
24
25    def test_attribute_error_w_class_methods(self):
26        src.attribute_error.AClass.method_00()
27        src.attribute_error.AClass.method_01()
28        src.attribute_error.AClass.method_02()
29        src.attribute_error.AClass.method_03()
30
31
32# Exceptions seen
33# AssertionError
34# AttributeError
35# NameError
36# TypeError
37# SyntaxError

start the project

  • I name this project attribute_error

  • I open a terminal

  • I make a directory for the project

    mkdir attribute_error
    

    the terminal goes back to the command line

  • I change directory to the project

    cd attribute_error
    

    the terminal shows I am in the attribute_error folder

    .../pumping_python/attribute_error
    
  • I make a directory for the source code

    mkdir src
    

    the terminal goes back to the command line

  • I make a Python file to hold the source code in the src directory

    touch src/attribute_error.py
    

    Note

    on Windows without Windows Subsystem for Linux use New-Item src/attribute_error.py instead of touch src/attribute_error.py

    New-Item src/attribute_error.py
    

    the terminal goes back to the command line

  • I make a directory for the tests

    mkdir tests
    

    the terminal goes back to the command line

  • I make the tests directory a Python package

    Danger

    use 2 underscores (__) before and after init for __init__.py not _init_.py

    touch tests/__init__.py
    

    Note

    on Windows without Windows Subsystem for Linux use New-Item tests/__init__.py instead of touch tests/__init__.py

    New-Item tests/__init__.py
    

    the terminal goes back to the command line

  • I make a Python file for the tests in the tests directory

    touch tests/test_attribute_error.py
    

    Note

    on Windows without Windows Subsystem for Linux use New-Item tests/test_attribute_error.py instead of touch tests/test_attribute_error.py

    New-Item tests/test_attribute_error.py
    

    the terminal goes back to the command line

  • I open test_attribute_error.py in the editor of the Integrated Development Environment (IDE)

    Tip

    I can open a file from the terminal in the Integrated Development Environment (IDE) with the name of the program and the name of the file. That means if I type this in the terminal

    code tests/test_attribute_error.py
    

    Visual Studio Code opens test_attribute_error.py in the editor

  • I add the first failing test to test_attribute_error.py

    1import unittest
    2
    3
    4class TestAttributeError(unittest.TestCase):
    5
    6    def test_failure(self):
    7        self.assertFalse(True)
    
  • I make a requirements file for the Python packages I need, in the terminal

    echo "pytest" > requirements.txt
    

    the terminal goes back to the command line

  • I add pytest-watcher to the file

    echo "pytest-watcher" >> requirements.txt
    

    the terminal goes back to the command line

  • I setup the project with uv

    uv init
    

    the terminal shows

    Initialized project `attribute_error`
    

    then goes back to the command line

  • I remove main.py from the project because I do not use it

    rm main.py
    

    the terminal goes back to the command line

  • I install the Python packages I gave in the requirements file

    uv add --requirement requirements.txt
    

    the terminal shows it installed the Python packages

  • I use pytest-watcher to run the tests automatically

    uv run pytest-watcher . --now
    

    the terminal shows

    ================================ FAILURES ================================
    ____________________ TestAttributeError.test_failure _____________________
    
    self = <tests.test_attribute_error.AttributeError testMethod=test_failure>
    
        def test_failure(self):
    >       self.assertFalse(True)
    E       AssertionError: True is not false
    
    tests/test_attribute_error.py:7: AssertionError
    ======================== short test summary info =========================
    FAILED tests/test_attribute_error.py::TestAttributeError::test_failure - AssertionError: True is not false
    =========================== 1 failed in X.YZs ============================
    
  • I add AssertionError to the list of Exceptions seen in test_attribute_error.py in the editor

     4class TestAttributeError(unittest.TestCase):
     5
     6    def test_failure(self):
     7        self.assertFalse(True)
     8
     9
    10# Exceptions seen
    11# AssertionError
    
  • then I change True to False in the assertion

    7        self.assertFalse(False)
    

    the test passes


test_attribute_error_w_variables


RED: make it fail


  • I add an import statement at the top of test_attribute_error.py

    1import src.attribute_error
    2import unittest
    
  • I change test_failure to test_attribute_error_w_variables

     5class TestAttributeError(unittest.TestCase):
     6
     7    def test_attribute_error_w_variables(self):
     8        src.attribute_error.variable_00
     9
    10
    11# Exceptions seen
    

    I think of src.attribute_error.variable_00 as an address

    • src is the src folder

    • src.attribute_error points to attribute_error.py in the src folder

    • src.attribute_error.variable_00 points to variable_00 in attribute_error.py in the src folder

    Since attribute_error.py is empty, Python cannot find variable_00 inside it and raises AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'variable_00'
    

    variable_00 is NOT an attribute of attribute_error.py in the src folder

  • I add AttributeError to the list of Exceptions seen in test_attribute_error.py

    11# Exceptions seen
    12# AssertionError
    13# AttributeError
    

GREEN: make it pass


  • I open attribute_error.py from the src folder in the editor of my Integrated Development Environment (IDE)

  • I add the name to attribute_error.py

    1variable_00
    

    the terminal shows NameError

    NameError: name 'variable_00' is not defined
    

    NameError is raised when I use a name that is not defined in the file I am working in

  • I add NameError to the list of Exceptions seen in test_attribute_error.py

    11# Exceptions seen
    12# AssertionError
    13# AttributeError
    14# NameError
    
  • I point variable_00 to None in attribute_error.py

    1variable_00 = None
    

    the test passes.

variable_00 is now an attribute or property of attribute_error.py in the src folder, I can use it with src.attribute_error.variable_00


REFACTOR: make it better


  • I do the same test a few more times as a drill in test_attribute_error.py

    7    def test_attribute_error_w_variables(self):
    8        src.attribute_error.variable_00
    9        src.attribute_error.variable_01
    

    the terminal shows AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'variable_01'. Did you mean: 'variable_00'?
    
  • I add the name to attribute_error.py

    1variable_00 = None
    2variable_01
    

    the terminal shows NameError

    NameError: name 'variable_01' is not defined
    
  • I point it to None to define it

    1variable_00 = None
    2variable_01 = None
    

    the test passes

  • I add another statement to test_attribute_error.py

     7    def test_attribute_error_w_variables(self):
     8        src.attribute_error.variable_00
     9        src.attribute_error.variable_01
    10        src.attribute_error.variable_02
    

    the terminal shows AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'variable_02'. Did you mean: 'variable_00'?
    
  • I add the name and point it to None in attribute_error.py

    1variable_00 = None
    2variable_01 = None
    3variable_02 = None
    

    the test passes

  • one more line in test_attribute_error.py

     7    def test_attribute_error_w_variables(self):
     8        src.attribute_error.variable_00
     9        src.attribute_error.variable_01
    10        src.attribute_error.variable_02
    11        src.attribute_error.variable_03
    

    the terminal shows AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'variable_03'. Did you mean: 'variable_00'?
    
  • I add the attribute to attribute_error.py

    1variable_00 = None
    2variable_01 = None
    3variable_02 = None
    4variable_03 = None
    

    the test passes


test_attribute_error_w_functions


RED: make it fail


I add a new test to test_attribute_error.py

 5class TestAttributeError(unittest.TestCase):
 6
 7    def test_attribute_error_w_variables(self):
 8        src.attribute_error.variable_00
 9        src.attribute_error.variable_01
10        src.attribute_error.variable_02
11        src.attribute_error.variable_03
12
13    def test_attribute_error_w_functions(self):
14        src.attribute_error.function_00()
15
16
17# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.attribute_error' has no attribute 'function_00'

GREEN: make it pass


  • I add the name and point it to None in attribute_error.py

    1variable_00 = None
    2variable_01 = None
    3variable_02 = None
    4variable_03 = None
    5
    6
    7function_00 = None
    

    the terminal shows TypeError

    TypeError: 'NoneType' object is not callable
    
  • I add TypeError to the list of Exceptions seen in test_attribute_error.py

    17# Exceptions seen
    18# AssertionError
    19# AttributeError
    20# NameError
    21# TypeError
    
  • I change the variable to a function in attribute_error.py

    1variable_00 = None
    2variable_01 = None
    3variable_02 = None
    4variable_03 = None
    5
    6
    7def function_00():
    8    return None
    

    the test passes.

function_00 is now an attribute or property of attribute_error.py in the src folder. I can call it with src.attribute_error.function_00()


REFACTOR: make it better


  • time to do it as a drill, I add another call in test_attribute_error.py

    13    def test_attribute_error_w_functions(self):
    14        src.attribute_error.function_00()
    15        src.attribute_error.function_01()
    

    the terminal shows AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'function_01'. Did you mean: 'function_00'?
    
  • I add the function to attribute_error.py

     7def function_00():
     8    return None
     9
    10
    11def function_01():
    12    return None
    

    the test passes

  • I add another line to test_attribute_error.py

    13    def test_attribute_error_w_functions(self):
    14        src.attribute_error.function_00()
    15        src.attribute_error.function_01()
    16        src.attribute_error.function_02()
    

    the terminal shows AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'function_02'. Did you mean: 'function_00'?
    
  • I add a function for it in attribute_error.py

     7def function_00():
     8    return None
     9
    10
    11def function_01():
    12    return None
    13
    14
    15def function_02():
    16    return None
    

    the test passes

  • I add another failing line in test_attribute_error.py

    13    def test_attribute_error_w_functions(self):
    14        src.attribute_error.function_00()
    15        src.attribute_error.function_01()
    16        src.attribute_error.function_02()
    17        src.attribute_error.function_03()
    18
    19
    20# Exceptions seen
    

    the terminal shows AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'function_03'. Did you mean: 'function_00'?
    
  • I add the function to attribute_error.py

     7def function_00():
     8    return None
     9
    10
    11def function_01():
    12    return None
    13
    14
    15def function_02():
    16    return None
    17
    18
    19def function_03():
    20    return None
    

    the test passes.


test_attribute_error_w_class_attributes

I know that variables and functions in a module are attributes of the module.

A class in a module is also an attribute of the module, and variables in the class are attributes of the class.


RED: make it fail


I add a new test to test_attribute_error.py

13    def test_attribute_error_w_functions(self):
14        src.attribute_error.function_00()
15        src.attribute_error.function_01()
16        src.attribute_error.function_02()
17        src.attribute_error.function_03()
18
19    def test_attribute_error_w_class_attributes(self):
20        src.attribute_error.AClass.attribute_00
21
22
23# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.attribute_error' has no attribute 'AClass'

GREEN: make it pass


  • I add a function to attribute_error.py

    19def function_03():
    20    return None
    21
    22
    23def AClass():
    24    return None
    

    the terminal shows AttributeError

    AttributeError: 'function' object has no attribute 'attribute_00'
    
  • I add a variable inside the function

    23def AClass():
    24
    25    attribute_00 = None
    26    return None
    

    the terminal still shows the same Exception because I cannot get to a variable inside a function from outside the function

  • I use the class keyword instead of the def keyword to make AClass a class

    23class AClass():
    24
    25    attribute_00 = None
    26    return None
    

    the terminal shows SyntaxError

    E    return None
    E    ^^^^^^^^^^^
    E  SyntaxError: 'return' outside function
    

    I cannot use a return statement outside a function

  • I add SyntaxError to the list of Exceptions seen in test_attribute_error.py

    23# Exceptions seen
    24# AssertionError
    25# AttributeError
    26# NameError
    27# TypeError
    28# SyntaxError
    
  • I remove the return statement from AClass in attribute_error.py since it is no longer a function

    23class AClass():
    24
    25    attribute_00 = None
    

    the test passes.

attribute_00 is now an attribute of the AClass class which is an attribute of attribute_error.py in the src folder and I can get to it with src.attribute_error.AClass.attribute_00


REFACTOR: make it better


  • I add another failing line for practice to test_attribute_error.py

    19    def test_attribute_error_w_class_attributes(self):
    20        src.attribute_error.AClass.attribute_00
    21        src.attribute_error.AClass.attribute_01
    22
    23
    24# Exceptions seen
    

    the terminal shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'attribute_01'. Did you mean: 'attribute_00'?
    
  • I add the name to the class definition in attribute_error.py

    23class AClass():
    24
    25    attribute_00 = None
    26    attribute_01 = None
    

    the test passes

  • I add another line to test_attribute_error.py

    19    def test_attribute_error_w_class_attributes(self):
    20        src.attribute_error.AClass.attribute_00
    21        src.attribute_error.AClass.attribute_01
    22        src.attribute_error.AClass.attribute_02
    

    the terminal shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'attribute_02'. Did you mean: 'attribute_00'?
    
  • I add the attribute to AClass in attribute_error.py

    23class AClass():
    24
    25    attribute_00 = None
    26    attribute_01 = None
    27    attribute_02 = None
    

    the test passes

  • I add another line to test_attribute_error.py

    19    def test_attribute_error_w_class_attributes(self):
    20        src.attribute_error.AClass.attribute_00
    21        src.attribute_error.AClass.attribute_01
    22        src.attribute_error.AClass.attribute_02
    23        src.attribute_error.AClass.attribute_03
    24
    25
    26# Exceptions seen
    

    the terminal shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'attribute_03'. Did you mean: 'attribute_00'?
    
  • I add the name to AClass in attribute_error.py

    23class AClass():
    24
    25    attribute_00 = None
    26    attribute_01 = None
    27    attribute_02 = None
    28    attribute_03 = None
    

    the test passes.


test_attribute_error_w_class_methods

I know that variables, functions and classes in a module are attributes of the module.

I also know that variables in a class are attributes of the class.

functions in a class are also attributes, they are called methods


RED: make it fail


  • I add a new test to test_attribute_error.py

    19    def test_attribute_error_w_class_attributes(self):
    20        src.attribute_error.AClass.attribute_00
    21        src.attribute_error.AClass.attribute_01
    22        src.attribute_error.AClass.attribute_02
    23        src.attribute_error.AClass.attribute_03
    24
    25    def test_attribute_error_w_class_methods(self):
    26        src.attribute_error.AClass.method_00()
    27
    28
    29# Exceptions seen
    

    the terminal shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'method_00'
    

GREEN: make it pass


  • I add the name to AClass and point it to None, in attribute_error.py

    23class AClass():
    24
    25    attribute_00 = None
    26    attribute_01 = None
    27    attribute_02 = None
    28    attribute_03 = None
    29
    30    method_00 = None
    

    the terminal shows TypeError

    TypeError: 'NoneType' object is not callable
    

    method_00 points to None and I cannot call None like a function

  • I make it a method with the def keyword

    23class AClass():
    24
    25    attribute_00 = None
    26    attribute_01 = None
    27    attribute_02 = None
    28    attribute_03 = None
    29
    30    def method_00():
    31        return None
    

    the test passes.

method_00 is now an attribute of AClass which is an attribute of attribute_error.py in the src folder and I can call it with src.attribute_error.AClass.method_00()


REFACTOR: make it better


  • You know the “drill”, I add a new failing line to test_attribute_error.py

    25    def test_attribute_error_w_class_methods(self):
    26        src.attribute_error.AClass.method_00()
    27        src.attribute_error.AClass.method_01()
    

    the terminal shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'method_01'. Did you mean: 'method_00'?
    
  • I add a definition for it in attribute_error.py

    30    def method_00():
    31        return None
    32
    33    def method_01():
    34        return None
    

    the test passes

  • I add another failing line to test_attribute_error.py

    25    def test_attribute_error_w_class_methods(self):
    26        src.attribute_error.AClass.method_00()
    27        src.attribute_error.AClass.method_01()
    28        src.attribute_error.AClass.method_02()
    

    the terminal shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'method_02'. Did you mean: 'method_00'?
    
  • I add the method to AClass in attribute_error.py

    30    def method_00():
    31        return None
    32
    33    def method_01():
    34        return None
    35
    36    def method_02():
    37        return None
    

    the test passes

  • I add the last line to test_attribute_error.py

    25    def test_attribute_error_w_class_methods(self):
    26        src.attribute_error.AClass.method_00()
    27        src.attribute_error.AClass.method_01()
    28        src.attribute_error.AClass.method_02()
    29        src.attribute_error.AClass.method_03()
    30
    31
    32# Exceptions seen
    

    the terminal shows AttributeError

    AttributeError: type object 'AClass' has no attribute 'method_03'. Did you mean: 'method_00'?
    
  • I add the method to AClass in attribute_error.py

    30class AClass():
    31
    32    attribute_00 = None
    33    attribute_01 = None
    34    attribute_02 = None
    35    attribute_03 = None
    36
    37    def method_00():
    38        return None
    39
    40    def method_01():
    41        return None
    42
    43    def method_02():
    44        return None
    45
    46    def method_03():
    47        return None
    

    the test passes.


close the project

  • I close attribute_error.py and test_attribute_error.py in the editors

  • I click in the terminal, then use q on the keyboard to leave the tests. The terminal goes back to the command line

  • I change directory to the parent of attribute_error

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory


review

I ran tests for AttributeError with

I also saw these Exceptions


code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

you know

Would you like to test how to pass values from tests to functions with assert methods?


rate pumping python

If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too