AttributeError: module 'X' has no attribute 'Y' in Python

avatar
Borislav Hadzhiev

Last updated: Apr 8, 2024
5 min

banner

# AttributeError: module 'X' has no attribute 'Y' in Python

The Python "AttributeError: module has no attribute" occurs for multiple reasons:

  1. Having a circular dependency between files, e.g. file A imports file B and vice versa.
  2. Having a local module with the same name as an imported module.
  3. Having an incorrect import statement. (use print(dir(your_module)) to see what you imported)
  4. Trying to access an attribute that doesn't exist on the module.

attributeerror module has no attribute

# Don't name local files with a name of a third-party module

Here is an example of how the error is caused when an imported module is shadowed by a local file with the same name.

This is a file named main.py that makes use of the requests module.

main.py
import requests # ๐Ÿšจ IMPORTANT: Print the attributes of what you imported print(dir(requests)) def make_request(): # โ›”๏ธ AttributeError: module 'requests' has no attribute 'get' res = requests.get('https://reqres.in/api/users') parsed = res.json() print(parsed) make_request()

having local module with clashing name

However, I have a local file called requests.py which shadows the official requests module and causes the error.

requests.py
def greet(): print('bobbyhadz.com')

dont name local modules with clashing names

This can also happen when you give a module the same name as a standard-library module, e.g. datetime.

You can use the sys module to print all of the built-in module's names if you ever wonder if your local modules are clashing with built-in ones.

main.py
import sys # ๐Ÿ‘‡๏ธ print all built-in module names print(sys.builtin_module_names)

The error is also caused if one of the modules you are importing imports a module that has the same name as a local file in your project.

For example, if you import requests and requests imports datetime, but you have a local file called datetime.py, you would still get the error.

The Python interpreter first looks for the imported module in the built-in modules, then in the current directory, then in the PYTHON PATH, then in the installation-dependent default directory.

So, when we create a local file with the same name as that of a third-party module, we effectively shadow the official module with our local file.

Make sure you haven't named your local modules with names of remote modules, e.g. datetime.py or requests.py and remove any circular dependencies in import statements.

A good way to start debugging is to print(dir(your_module)) and see what attributes the imported module has.

main.py
import requests # ['__builtins__', '__cached__', '__doc__', '__file__', # '__loader__', '__name__', '__package__', '__spec__', 'greet'] print(dir(requests))

If we look at the attributes the imported requests module has, we can see our greet function and none of the actual methods of the official requests module.

This is a clear indication, that we are shadowing the third-party module with our local module.

# Make sure you haven't written your import statement incorrectly

This approach can also help you if you have an incorrect import statement.

Look at the attributes of the module you are importing and make sure you haven't written your import statement incorrectly.

# Make sure you don't have circular imports

Another common cause of the error is having circular imports between files.

Let's look at an example that uses the modules first_module.py and second_module.py.

Here is the code for first_module.py:

first_module.py
# ๐Ÿ‘‡๏ธ imports second_module import second_module def first_function(): print('first function') # โ›”๏ธ AttributeError: partially initialized module 'second_module' # has no attribute 'second_function' (most likely due to a circular import) second_module.second_function()

And here is the code for second_module.py:

second_module.py
# ๐Ÿ‘‡๏ธ imports first_module import first_module def second_function(): print('second function') first_module.first_function()

Notice that the two modules import each other. This is called a circular dependency.

One way to get around two modules depending on one another is to nest the import statement in a function scope.

Here is the updated second_module.py file.

second_module.py
def second_function(): print('second function') # ๐Ÿ‘‡๏ธ now importing in a function scope import first_module first_module.first_function()
Now that we don't import at the outermost scope in both modules, the order of imports does not cause the interpreter to error out.

However, a much better approach is to create a file third_module.py which imports first_module and second_module and uses them.

Here is the updated code for first_module.py.

first_module.py
def first_function(): print('first function')

Here is the updated code for second_module.py.

second_module.py
def second_function(): print('second function')

And here is the code for third_module.py which makes use of both of the previous modules.

third_module.py
import first_module import second_module first_module.first_function() second_module.second_function()

Now we don't have any circular imports (importing members between the same modules), which makes our code much easier to reason about.

If you have two modules that import each other, it's a good time to create a third module that imports the previous two.

# Print all of the attributes of the imported module

If none of the suggestions helped, use the dir() function to print all of the attributes the imported module has.

main.py
import requests # ['__builtins__', '__cached__', '__doc__', '__file__', # '__loader__', '__name__', '__package__', '__spec__', 'greet'] print(dir(requests))

If you pass a module object to the dir() function, it returns a list of names of the module's attributes.

If you try to access any attribute that is not in this list, you will get the "AttributeError: module has no attribute".

This means that you are either trying to access an attribute that is not present on the module, or you have an incorrect import statement.

Consider the following example.

We have a module called another_file.py that has an Employee class.

another_file.py
class Employee: def __init__(self, name): self.name = name def greet(self): return f'Hello {self.name}'

And we have a file called main.py which imports from another_file.py.

main.py
import another_file # ['Employee', '__builtins__', '__cached__', '__doc__', # '__file__', '__loader__', '__name__', '__package__', '__spec__'] print(dir(another_file)) # โ›”๏ธ AttributeError: module 'another_file' has no attribute 'greet' another_file.greet()

Notice that we are trying to access the greet method on the module object, even though we haven't created an instance of the class first.

If we look at the output of calling the dir() function, we can see that the module has an Employee attribute.

main.py
import another_file emp = another_file.Employee('Bobby Hadz') # ๐Ÿ‘‡๏ธ Hello Bobby Hadz print(emp.greet())

To solve the error, we first created an instance and called the method on the instance, rather than on the module object.

# Conclusion

To solve the Python "AttributeError: module has no attribute", make sure you haven't named your local modules with names of remote modules, e.g. datetime.py or requests.py and remove any circular dependencies in import statements.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev