ImportError – Cannot Import Name X in Python

ImportError occurs when Python is unable to load an attribute (class, method, or variable) from a module. The following are common reasons why that happens:

  • The imported attribute does not exist or is misspelled,
  • There is a circular dependency between the script being executed and the module is loaded,
  • The imported attribute is not available in the Python library of packages, and,
  • Naming scripts after installed modules

In the coming sections, we will discuss these causes and provide a solution for each case.

The imported attribute does not exist or is misspelled

In this case, the function/class/variable we are trying to load does not exist. This can arise when we misspell the attribute we intend to import, or it is just not created. For example, suppose we have two scripts, executing_script.py, and math2.py, in the same folder. We intend to run executing_scipt.py to call some functions in math2.py.

File:math2.py

from numpy import exp
#from numpy module we import exp, the Euler's number, e,

# exp(1)=e^1 is approximately 2.7182...

def discount(rate, price):
	return rate*price +exp(rate)
def discounted_price(rate, price):
	return (1-rate)*price -exp(rate)

In the executing_script.py script, we intend to import and use the discounted_price() function from math2.py.

File: executing_script.py

from math2 import discount_price
discount_price(0.1, 980)

Output (running executing_script.py):

ImportError: cannot import name 'discount_price' from 'math2'

We misspelled the function, hence the error.

Solution

To fix the ImportError of this kind, we need to ensure that the attribute(s) we are importing exists. In the case above, we needed to import the discounted_price() function, not discount_price, as follows

File: executing_script.py

from math2 import discounted_price
print(discounted_price(0.1, 980))

Output:

880.8948290819244

Remember that we can also import the module math2.py and access its attributes as follows.

import math2
print(math2.discounted_price(0.1, 980))

Or, import all the attributes in the math2 module and use them as follows

# import all attributes on the math2 module

from math2 import *

marked_price = 645
rate = 0.1 #10 percent discount
print("Marked Price:", marked_price)
print("Discounted price:", discounted_price(0.1, marked_price))
print("The discount amount:", discount(0.1, marked_price))

Output:

Marked Price: 645
Discounted price: 579.3948290819244
The discount amount: 65.60517091807564

The imported attribute is not available in the Python library

The ImportError resulting here is the same as discussed in the first section. The only difference is that the library being loaded here is not user-defined (it is Python packages that come preinstalled or installed by pip).

For example, suppose we want to convert a Python list into a NumPy array using the NumPy package.

from numpy import arr
lst1 = [1, -4, 5, 6]
arr1 = arr(lst1)

Output:

ImportError: cannot import name 'arr' from 'numpy'

NumPy module does not have a function arr and therefore cannot be imported. What we are looking for, instead, is the “array” function.

from numpy import array
lst1 = [1, -4, 5, 6]
arr1 = array(lst1)

By importing the correct method, the error is fixed. As said earlier, you can also load the module and access the attribute it contains as follows. If the module is unavailable, as shown below, we run into another class of error AttributeError.

import numpy as np
lst1 = [1, -4, 5, 6]
arr1 = np.arr(lst1)

Output:

AttributeError: module 'numpy' has no attribute 'arr'

The error explains it well; the “arr” attribute is not in numpy.

Circular Dependency

Circular dependency imports occur when two scripts are interdependent – the script being executed (script A) imports attribute(s) from the second script (script B), which also calls some attributes on the script being executed (script A).

Figure : A circular dependency import (Source: Author).

This circular dependency occurs because the module loading process cannot be completed. To understand why this is so, let us see an example.

File: physics1.py

from math1 import multiply
def acceleration(u, v, t):
	return (u*v)/t
def mc(m, c):
	return m*(c**2)
a = multiply(9, 10)
print(a)

File: math1.py

from physics1 import acceleration, mc
def multiply(a, b):
	return a*b
acc = acceleration(2, 8, 2)
print(acc)
E = mc(4, 2.4)
print(E)

When we execute the math1.py script, we run into ImportError with the description below:

ImportError: cannot import name ‘acceleration’ from partially initialized module ‘physics1’ (most likely due to a circular import)

Python detected a circular import and stopped the execution. The attempt to import modules in this manner can run indefinitely because the module will be partially initialized at every import — because of using from A import attr1.

The script math1.py tries to import acceleration() and mc() in physics1, and even before that is done, physics1.py also tries to import an attribute in math1.py.

There are different ways to solve this. We will discuss two in this article.

Solution 1: Defer the importation

When we run math1.py, we import two functions: acceleration and mc. Circular dependency arises because before these methods are imported, physics1.py is also trying to import from math1.py. To fix this problem, we can import functions on math1.py after importing the two functions.

File: physics1.py

def acceleration(u, v, t):
	return (u*v)/t
def mc(m, c):
	return m*(c**2)
# put the attributes that cause circular dependency before the import statement
from math1 import multiply
a = multiply(9, 10)
print(a)

File: math1.py

from physics1 import acceleration, mc
def multiply(a, b):
	return a*b
acc = acceleration(2, 8, 2)
print(acc)
E = mc(4, 2.4)
print(E)

Output (when we execute math1.py):

8.0
23.04
90
8.0
23.04

Note: When attributes are imported, the entire module is scanned. That is why the acceleration() and mc() function prints the output on executing math1.py and also on the import line in physics1.py (from math1 import multiply).

Solution 2: Transfer attributes to a third file

This is probably the best way to deal with circular imports because it gives us a clean code (according to PEP standards it is a good idea to keep imports at the top of the file), and it is straightforward and also efficient.

In this case, we will take all the functions into a script named “third.py” and call them from that central point.

File: third.py

def multiply(a, b):
	return a*b
def acceleration(u, v, t):
	return (u*v)/t
def mc(m, c):
	return m*(c**2)

File: math3.py

from third import acceleration, mc, multiply
acc = acceleration(2, 8, 2)
print(acc)
E = mc(4, 2.4)
print(E)
a = multiply(9, 10)
print(a)

Output:

8.0
23.04
90

Naming scripts after installed modules

When naming Python scripts, we should avoid giving them names matching the installed packages. This is because if we try importing a user-defined module with a name similar to an installed package Python will throw an ImportError. Let’s see an example.

In this example, we have two scripts named math.py and script1.py in the same directory.

File: math.py

def add2(a, b):
	return a + b

File: script1.py

from math import add2
print(add2(9, 8))

On executing script1.py, we get the following error message:

ImportError: cannot import name ‘add2’ from ‘math’ (unknown location)

When importing modules, Python looks for these packages in specific places – among them is the current working directory and the default package location created during Python installation.

In our current directory, we have a user-defined module named math when we are executing script1.py. There exists also a preinstalled package called math. In this case, therefore, Python loads the preinstalled math and does not see the math.py script in our current working directory.

The error in this category can be solved by simply avoiding the use of names matching the installed packages for our user-defined modules.

Conclusion

ImportError occurs because Python is unable to import the attributes we are trying to load. This can happen because of several reasons.

Firstly, the imported attribute might not exist or has been misspelled. In this case, you need to countercheck the names of the attributes you are trying to import.

Secondly, we can run into circular dependence during importation. This happens when two scripts are trying to import each other.

We discussed two solutions for this problem and alluded that the best one is to move functions into a single file and import them from there.

Lastly, we covered an ImportError related to how we name our user-defined modules. If we give a name that matches the installed package to our user-defined modules, Python may default to incorrectly loading system-wide packages.