what causes AttributeError?


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


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 unittest
 2import src.attribute_error
 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

  • then I make a directory for the project

    mkdir attribute_error
    

    the terminal goes back to the command line

    .../pumping_python
    
  • I change directory to the project

    cd attribute_error
    

    the terminal shows I am now in the attribute_error folder

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

    mkdir src
    

    the terminal goes back to the command line

    .../pumping_python/attribute_error
    
  • I use touch to make an empty file for the program in the src folder

    touch src/attribute_error.py
    

    Attention

    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

    .../pumping_python/attribute_error
    
  • I make a directory for the tests

    mkdir tests
    

    the terminal goes back to the command line

  • I use touch to make an empty file in the tests folder to tell Python that it is a Python package

    Attention

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

    touch tests/__init__.py
    

    Attention

    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 an empty file for the actual test

    touch tests/test_attribute_error.py
    

    Attention

    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 Visual Studio Code by typing code and the name of the file, for example, when I type this

    code tests/test_attribute_error.py
    

    test_attribute_error.py opens up 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 virtual environment in the terminal

    python3 -m venv .venv
    

    Attention

    on Windows without Windows Subsystem for Linux use python3 -m venv .venv instead of python3 -m venv .venv

    python -m venv .venv
    

    the terminal takes some time then goes back to the command line

  • I activate the virtual environment

    source .venv/bin/activate
    

    Attention

    on Windows without Windows Subsystem for Linux use .venv/bin/activate.ps1 NOT source .venv/bin/activate

    .venv/scripts/activate.ps1
    

    the terminal shows

    (.venv) .../pumping_python/attribute_error
    
  • I upgrade the Python package manager (pip) to the latest version

    python3 -m pip install --upgrade pip
    

    the terminal shows pip being uninstalled then installs the latest version or shows that it is already the latest version

  • I make a requirements.txt file for the Python programs my project needs

    echo "pytest-watch" > requirements.txt
    

    the terminal goes back to the command line

  • I use pip to install pytest-watch with the requirements file

    python3 -m pip install --requirement requirements.txt
    

    Attention

    on Windows without Windows Subsystem for Linux use python -m pip install --requirement requirements.txt instead of python3 -m pip install --requirement requirements.txt

    python -m pip install --requirement requirements.txt
    

    the terminal shows pip downloads and installs the Python programs that pytest-watch needs to run

  • I use pytest-watch to run the test

    pytest-watch
    

    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_functions.py::TestFunctions::test_failure - AssertionError: True is not false
    =========================== 1 failed in X.YZs ============================
    
  • I hold ctrl (Windows/Linux) or option/command (MacOS) on the keyboard and use the mouse to click on tests/test_attribute_error.py:7 to open it in the editor

  • I add AssertionError to the list of Exceptions seen in test_functions.py

     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

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

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

    • src.attribute_error.variable_00 is pointing 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 the terminal shows AttributeError

    AttributeError: module 'src.attribute_error' has no attribute 'variable_00'
    
  • 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), then I add a name

    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 which is in the src folder and I can get to 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 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

    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

  • A variable in a class in a module is an attribute of class


test_attribute_error_w_functions


RED: make it fail


I add a new test to test_attribute_error.py

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

    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

    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

    11def function_01():
    12    return None
    13
    14
    15def function_02():
    16    return None
    

    the test passes

  • I add another 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

    15def function_02():
    16    return None
    17
    18
    19def function_03():
    20    return None
    

    the test passes.

  • A function in a module is an attribute of the module

  • A variable in a class in a module is an attribute of class


test_attribute_error_w_class_attributes

I know that variables and functions defined in a module are attributes. variables defined inside a class are also attributes.


RED: make it fail


I add a new test to test_attribute_error.py

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

    15def function_03():
    16    return None
    17
    18
    19def AClass():
    20    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 which is 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
    

    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

  • A variable in a class in a module is an attribute of class

  • A class in a module is an attribute of the module

  • A function in a module is an attribute of the module

  • A variable in a class in a module is an attribute of class


test_attribute_error_w_class_methods

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

I also know that variables defined inside a class are attributes. functions defined inside a class are also attributes, they are called methods


RED: make it fail


  • I add a new test to test_attribute_error.py

    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
    
  • I make it a method with the def keyword

    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 which is in the src folder and I can get to it with src.attribute_error.AClass.method_00()


REFACTOR: make it better



close the project

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

  • I click in the terminal and exit the tests with ctrl+c on the keyboard

  • I deactivate the virtual environment

    deactivate
    

    the terminal goes back to the command line, (.venv) is no longer on the left side

    .../pumping_python/attribute_error
    
  • 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 the following 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 leave a 5 star review. It helps other people get into the book too