Report this

What is the reason for this report?

How To Import Modules in Python 3

Updated on September 15, 2025
How To Import Modules in Python 3

Introduction

While the Python programming language is equipped with a useful set of built-in functions like print() and len(), these provide only a foundation for basic programs. To unlock Python’s true potential and build more sophisticated applications, you must leverage modules. Modules are the cornerstone of modern Python development, allowing you to incorporate powerful, pre-written functionality into your projects. Mastering how to find, install, and use these modules is a fundamental skill for any Python programmer.

In this comprehensive guide, we will walk you through the entire life cycle of working with Python modules. We will start with the fundamentals, such as installing packages with pip and using basic import statements. From there, we will dive into advanced topics essential for writing scalable and maintainable code. We will equip you with the knowledge to diagnose and fix issues like circular imports, define a module’s public API with the __all__ variable, structure large-scale applications with namespace packages, and dynamically load code using the importlib module. By the end, you’ll be ready to manage dependencies in any project with confidence.

Key Takeaways:

  • A module is a single .py file, a package is a directory of modules, and a library is a collection of packages that provide specific functionality.
  • Use the pip install <module_name> command to download and install third-party packages from the Python Package Index (PyPI).
  • Use the standard import module_name syntax to keep code clear and avoid namespace conflicts; always avoid wildcard imports (from module import *).
  • Python finds modules by searching a list of directories in sys.path, starting with the current script’s directory.
  • Resolve circular imports, where two modules depend on each other, by refactoring your code or using local (in-function) imports.
  • Use the __all__ variable to explicitly define the public API of a module that gets imported during a wildcard import.
  • Leverage namespace packages to create a single package that spans multiple directories, which is ideal for large applications or plugin systems.
  • Use the importlib module to import modules programmatically using their string names, enabling dynamic code loading.
  • Improve code readability by grouping imports at the top of your file in the standard order: standard library, third-party, then local.
  • Troubleshoot a ModuleNotFoundError by checking if the module is installed and spelled correctly, and an ImportError by verifying the function’s name.

Prerequisites

Before you begin, ensure you have the following prerequisites:

  • Python 3 installed on your computer or server.
  • A programming environment set up for Python development.

If you need help setting up your environment, refer to these tutorials:

What are Python Modules?

A module is any Python file (.py) that contains functions, classes, or variables and can be imported into other Python code. A Python file called hello.py has the module name of hello that can be imported into other Python files or used on the Python command line interpreter. You can learn about creating your modules by reading How To Write Modules in Python 3.

Modules can define functions, classes, and variables that you can reference in other Python .py files or via the Python command line interpreter.

Modules serve as a powerful mechanism to logically arrange your Python code, improving its readability, maintainability, and understandability. Instead of having one massive script, you can break your program down into smaller, more focused modules.

The primary purpose of modules revolves around following software engineering best practices:

  • Code reusability: Instead of writing the same function or class multiple times across different parts of your application, you can define it once in a module and then reuse it wherever needed by simply importing that module. This saves time, reduces errors, and makes your codebase cleaner and more efficient.
  • Maintainability: By breaking down a large, complex program into smaller, logical modules, you create a more manageable structure. If you need to fix a bug or add a new feature, you know exactly which module to check, rather than sifting through thousands of lines of code.
  • Organization: Modules provide a clear and logical way to arrange your Python code. Related functions, classes, and variables can be grouped within a single module, making your project’s structure intuitive and easy to navigate for anyone who needs to understand the codebase.
  • Namespace isolation: Each module has its private namespace. This means that variables, functions, and classes defined within one module won’t accidentally conflict with identically named elements in another module, preventing naming collisions and making your code more robust.
  • Collaboration: When working on a project, modules allow multiple developers to work on different parts of the application simultaneously without stepping on each other’s toes. Each developer can focus on assigned modules, reducing the risk of accidental conflicts.

What are Modules vs. Packages vs. Libraries?

While often used interchangeably, “module”, “package”, and “library” have distinct meanings within the Python ecosystem:

  • Module: The most granular unit, a module is a single .py file containing Python code. When you import a module, you bring its definitions and statements into your current script’s namespace.
  • Package: A package is a collection of related modules organized in a directory hierarchy. The presence of an __init__.py file within a directory signals to Python that it’s a package. This allows for a more structured way to manage multiple modules that work together.
  • Library: This is the broadest term, referring to a collection of pre-written code used to perform specific tasks. A library can be composed of single modules, multiple packages, or a mix of both. The Python Standard Library is a prime example, offering a vast array of functionalities. Essentially, all packages are a type of library, burt not all libraries are necessarily structured as multi-module packages.

How to Check For and Install Modules?

In Python, modules are accessed by using the import statement. When you do this, you execute the code of the module, keeping the scopes of the definitions so that your current file(s) can make use of these.

There are a number of modules that are built into the Python Standard Library, which contains many modules that provide access to system functionality or provide standardized solutions. The Python Standard Library is part of every Python installation.

Check if a Module is Installed

Before you try to install a module, it’s good practice to check if it’s already on your system. The most direct way to do this is by trying to import it in a Python interactive session.

First, open your command line or terminal and start the Python interpreter:

python3

You should see the Python prompt (>>>), indicating the interpreter is ready for commands.

Let’s first try to import a built-in module, like math.

>>> import math
>>>

Since math is part of the Standard Library, the import succeeds without any message, and you are returned to the prompt. This confirms the module is available.

Now, let’s try to import a popular third-party module that may not be installed, such as matplotlib, a library for data visualization.

>>> import matplotlib

If matplotlib is not installed on your system, the interpreter will raise an ImportError. This is the standard way Python signals that a module could not be found.

Output
Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 'matplotlib'

Seeing an ImportError is a clear sign that you need to install the module before you can use it.

How to Install the Module Using pip?

pip is the package installer for Python. You use it to install and manage additional libraries and dependencies that are not part of the standard library. These packages are typically downloaded from the Python Package Index (PyPI).

First, exit the Python interpreter. You can do this by typing exit() or by using the shortcut CTRL + D (on Linux/macOS) or CTRL + Z then Enter (on Windows).

Now, from your regular command line prompt, use pip to install matplotlib:

pip install matplotlib

pip will connect to PyPI, download the matplotlib package and any other packages it depends on (its dependencies), and install them into your Python environment.

How to Verify the Installation?

Once the installation is complete, it’s a good idea to verify that the module is now available. Go back into the Python interpreter:

python3

And try the import statement again:

>>> import matplotlib
>>>

This time, the command should complete without any errors, returning you to the prompt. This confirms that matplotlib has been successfully installed and is now ready to be used in your programs.

Basic Importing Syntax

To use modules in your Python programs, you must first bring them into your script’s scope. This is done using the import statement. Python offers several ways to structure your import statements, each with its specific use case. Understanding these different syntaxes is fundamental to writing clean, efficient, and readable Python code.

This section will cover the primary methods for importing modules and their components.

How to Use import module_name?

The most straightforward way to import a module is with the import keyword followed by the module’s name. This is the recommended approach for most situations.

import math

When you use this syntax, you load the entire module into your program. The module’s contents (its functions, classes, and variables) are kept within their own namespace. To access any of them, you must prefix them with the module’s name and a dot (.). This is known as dot notation.

Let’s create a simple program that uses the math module to calculate the square root of a number and to access the value of Pi.

find_hypotenuse.py

import math

a = 3
b = 4

a_squared = math.pow(a, 2)
b_squared = math.pow(b, 2)

c = math.sqrt(a_squared + b_squared)

print("The hypotenuse of the triangle is:")
print(c)

print("The value of Pi is:")
print(math.pi)

In this example, we have to use math.pow(), math.sqrt(), and math.pi to access the pow function, the sqrt function, and the pi constant. If we had simply written sqrt(), our program would fail with an error because sqrt is not defined in our program’s main namespace.

When we run the program, we receive the following output:

Output
The hypotenuse of the triangle is: 5.0 The value of Pi is: 3.141592653589793

Using the import module_name syntax is explicit and clear. It makes your code easy to read because it is always obvious where a function or variable is coming from.

How to Use from module_name import function_name?

If you only need one or two specific items from a module and plan to use them frequently, you can import them directly into your program’s namespace using the from ... import syntax.

This approach allows you to call the function or variable by its name, without needing to use dot notation.

Let’s rewrite the previous example by importing only the sqrt and pi items from the math module.

find_hypotenuse_from.py

from math import sqrt, pi

a = 3
b = 4

# We can't use math.pow() because we did not import the whole module
# Instead, we can use the built-in exponentiation operator (**)
a_squared = a**2
b_squared = b**2

# Calculate the hypotenuse
c = sqrt(a_squared + b_squared)

print("The hypotenuse of the triangle is:")
print(c)

print("The value of Pi is:")
print(pi)

Notice that we can now use sqrt and pi directly. This can make your code slightly shorter. When you want to import multiple items from the same module, you can separate them with a comma, as we did with from math import sqrt, pi.

The output is identical to the previous example:

Output
The hypotenuse of the triangle is: 5.0 The value of Pi is: 3.141592653589793

While this method can be convenient, it can sometimes make code harder to read if many names are imported from various modules, as it becomes less clear where each function originated.

How to Import All Items with from module_name import *?

Python provides a syntax to import every public function, class, and variable from a module directly into your current namespace. This is done using an asterisk (*), which acts as a wildcard.

# This syntax is generally discouraged
from math import *

c = sqrt(25)
print(pi)

While this might seem like a convenient shortcut, it is strongly discouraged by the Python community’s best practices, including the official PEP 8 style guide. This practice is often referred to as a wildcard import.

There are several significant drawbacks to using wildcard imports:

  • Namespace Pollution: It dumps a large number of names into your local namespace. This can make it very difficult to understand which names are defined in your script versus which came from the imported module.
  • Reduced Readability: Anyone reading your code (including your future self) will have to guess the origin of a function. Code that explicitly uses math.sqrt() is far clearer than code that just uses sqrt().
  • Name Clashes: It dramatically increases the risk of a “naming collision.” If your script defines a function called sqrt() and you then use from math import *, your original function will be silently overwritten by the one from the math module. This can lead to subtle and hard-to-find bugs.

For these reasons, you should avoid wildcard imports in your code. The only exception is for certain modules specifically designed to be used this way, but even then, it should be done with caution. Sticking to import module_name is the safest and most readable approach for professional, maintainable code.

How to Use import module_name as alias?

Sometimes, a module’s name might be very long, or it might conflict with a name you are already using in your code. In these cases, Python allows you to create an alias or an alternate name for the module using the as keyword.

This is extremely common in the data science community, where libraries like numpy, pandas, and matplotlib have conventional aliases.

aliasing_example.py

import numpy as np
import matplotlib.pyplot as plt

# Create a simple array of data using numpy
x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 2, 4, 6, 8])

# Use matplotlib.pyplot to create a plot
plt.plot(x, y)
plt.title("My First Plot")
plt.xlabel("X-axis")
plt.ylabel("Y-axis")

plt.show() 

Here, instead of typing numpy.array(), we can use the much shorter np.array(). Similarly, plt.plot() is used instead of the more verbose matplotlib.pyplot.plot(). This practice makes code cleaner and faster to write without sacrificing readability, as these aliases are widely recognized conventions.

How does Python’s Module Search Path (sys.path) Work?

When you write an import my_module statement, how does Python know where to find that file? The answer lies in Python’s module search path, a predefined list of directories where the interpreter looks for modules. The interpreter searches these locations sequentially and uses the first matching file it finds.

The search order is as follows:

  • The Current Directory: The directory where the script you are running is located. This is the most common reason you can easily import a file that is in the same folder as your main script.
  • PYTHONPATH Directories: A list of directories you can set as an environment variable on your system. This feature allows you to place commonly used custom modules in a central location and access them from any project without modifying sys.path manually.
  • Standard Library Directories: The installation-dependent directories where Python’s built-in modules and standard libraries are stored. This is how Python finds modules like math, os, and json.

This list of directories is stored in a variable called path within the built-in sys module. You can inspect this list yourself to see exactly where Python is looking for modules on your system.

check_path.py
import sys
import pprint

print("Python will search for modules in the following directories:")
pprint.pprint(sys.path)

Running this script will print a list of strings, where each string is an absolute path to a directory. The very first item in the list is typically the directory of the script you just ran, which confirms it’s the first place Python searches.

Sample Output
Python will search for modules in the following directories: ['/root/python-code', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/usr/local/lib/python3.12/dist-packages', '/usr/lib/python3/dist-packages']

How to Create and Import Custom Modules?

One of the most powerful features of the import system is the ability to create and use your modules. This is a fundamental practice for organizing code in any application, as it allows you to separate concerns and improve maintainability.

Let’s create a simple project to demonstrate this. Imagine you have the following file structure:

my_app/
├── main.py
└── helpers.py

The helpers.py file contains a function that you want to use in your main application script. Any Python file can act as a module.

helpers.py
# This is a custom module with a helper function

def display_message(message, is_warning=False):
    if is_warning:
        print(f"WARNING: {message}")
    else:
        print(f"INFO: {message}")

# You can also define variables in a module
APP_VERSION = "1.0.2"

Because helpers.py is in the same directory as main.py (the first location in the sys.path search list), you can import it directly without any special configuration.

main.py
# Import our custom helpers module
import helpers

# You can also import specific items using the 'from' keyword
from helpers import APP_VERSION

print(f"Starting Application Version: {APP_VERSION}")

# Use a function from the helpers module using dot notation
helpers.display_message("The system is running normally.")
helpers.display_message("Disk space is critically low.", is_warning=True)

print("Application finished.")

When you run main.py, Python will find helpers.py in the current directory, load it as a module, and make its functions and variables available.

Output
Starting Application Version: 1.0.2 INFO: The system is running normally. WARNING: Disk space is critically low. Application finished.

This simple pattern is the foundation of creating multi-file applications in Python, allowing you to build clean, maintainable, and well-organized project structures.

Circular Imports

One of the most common and confusing issues developers face is the circular import. A circular import occurs when two or more modules depend on each other, creating a loop that Python cannot resolve during initialization.

What is a Circular Import and Why Does it Happen?

A circular import happens when Module A tries to import Module B, and Module B simultaneously tries to import Module A. When the Python interpreter loads module_a, it begins executing its code line by line. When it reaches import module_b, it pauses execution of module_a and starts loading module_b. However, if module_b contains an import module_a statement, the interpreter is asked to import a module that is already in the process of being imported but is not yet fully initialized.

This leads to an ImportError because one module will inevitably try to access an attribute from the other before it has been defined.

Let’s consider a practical example involving a web application with separate modules for database models and services.

models.py
from services import log_user_activity

class User:
    def __init__(self, name):
        self.name = name

    def perform_action(self):
        # A user action needs to be logged by the service
        print(f"User {self.name} is performing an action.")
        log_user_activity(self)

services.py
from models import User

def log_user_activity(user: User):
    # This service function needs to know about the User model
    print(f"Logging activity for user: {user.name}")

def create_user(name: str) -> User:
    return User(name)

# Example usage
if __name__ == '__main__':
    user = create_user("Alice")
    user.perform_action()

Here, models.py imports a function from services.py, and services.py imports the User class from models.py. If you try to run services.py, you will get the following error:

ImportError: cannot import name 'User' from partially initialized module 'models' (most likely due to a circular import)

Strategies to Resolve Circular Imports

Resolving circular imports usually involves rethinking your application’s structure to remove the circular dependency.

Refactoring and Dependency Inversion

The most robust solution is to refactor your code. Often, a circular dependency signals that a class or function is in the wrong place. You can introduce a third module for shared components or move the dependent code.

In our example, we could move the log_user_activity function to a separate logging.py module that depends on models.py, but services.py no longer needs to. Alternatively, you can use dependency inversion principles. Instead of models.py directly calling a service, it could dispatch an event that a logging service listens for.

Local Imports (Lazy Imports)

A quicker fix is to move the import statement inside the function or method that needs it. This is called a local or lazy import. The import is delayed until the function is actually called, by which time all modules will have been fully loaded.

Here’s how to fix models.py using a local import:

models.py

class User:
    def __init__(self, name):
        self.name = name

    def perform_action(self):
        # Import is moved inside the method
        from services import log_user_activity
        
        print(f"User {self.name} is performing an action.")
        log_user_activity(self)

This approach breaks the import loop at initialization time. However, it can make dependencies harder to track and introduces a small performance overhead on the first function call. It’s best used as a temporary solution or when a module is truly optional.

Using TYPE_CHECKING for Type Hints

If the circular dependency is only for type hinting (as in our services.py example), you can use the typing.TYPE_CHECKING constant. This constant is True only during static type checking and False at runtime, allowing you to import types for analysis without causing a runtime circular import.

services.py
from typing import TYPE_CHECKING

# The import is only processed by type checkers
if TYPE_CHECKING:
    from models import User

def log_user_activity(user: 'User'):
    print(f"Logging activity for user: {user.name}")

def create_user(name: str) -> 'User':
    # We need a real import for the constructor
    from models import User
    return User(name)

Notice that you must use the type name as a string ('User') when it’s behind a TYPE_CHECKING guard. While this solves the problem for type hints, you still need a local import for runtime logic, like instantiating the User class.

The __all__ Variable

When you design a Python module, you create a mix of public functions and classes intended for external use, as well as internal helper functions and constants. To explicitly define the public API of your module, you can use the __all__ variable.

The __all__ variable is a list of strings that declares which names should be exported when a wildcard import (from module import *) is used.

How to Use __all__

Consider a module that provides utility functions but also has some internal helpers.

string_utils.py

# Internal helper constant
_VOWELS = "aeiou"

def _count_vowels(text: str) -> int:
    # Internal helper to count vowels.
    return sum(1 for char in text.lower() if char in _VOWELS)

def public_capitalize(text: str) -> str:
    # Capitalizes the first letter of a string.
    return text.capitalize()

def public_reverse(text: str) -> str:
    # Reverses a string.
    return text[::-1]

Without __all__, if another script runs from string_utils import *, it will import _VOWELS, _count_vowels, public_capitalize, and public_reverse into its global namespace. This pollutes the namespace with internal implementation details.

By defining __all__, you can control this behavior.

string_utils.py (with `__all__`)

__all__ = ['public_capitalize', 'public_reverse']

# Internal helper constant
_VOWELS = "aeiou"

def _count_vowels(text: str) -> int:
    # Internal helper to count vowels.
    return sum(1 for char in text.lower() if char in _VOWELS)

def public_capitalize(text: str) -> str:
    # Capitalizes the first letter of a string.
    return text.capitalize()

def public_reverse(text: str) -> str:
    # Reverses a string.
    return text[::-1]

Now, from string_utils import * will only import public_capitalize and public_reverse. The internal helpers remain private to the module.

While using from module import * is generally discouraged in production code because it can make it unclear where a name comes from, __all__ serves as a crucial mechanism for library authors to create a clean and intentional public API.

Namespace Packages (PEP 420)

A namespace package is a collection of sub-packages that are spread across different locations on Python’s sys.path. The interpreter pieces them together at runtime to form a single, coherent package. Traditionally, a Python package is a directory containing an __init__.py file. Implicit namespace packages, introduced in PEP 420, allow you to create packages that span multiple directories without requiring an __init__.py file.

This is particularly useful for large libraries or applications where different components or plugins need to contribute to the same package namespace.

Imagine you’re building a large application with a plugin system. Each plugin should add its modules to the my_app.plugins namespace.

Here is the directory structure:

project_root/
├── app_core/
│   └── my_app/
│       └── plugins/
│           └── core_plugin.py
├── installed_plugins/
│   └── plugin_a/
│       └── my_app/
│           └── plugins/
│               └── feature_a.py
└── main.py

In this structure:

  • Neither my_app nor my_app/plugins contains an __init__.py file.
  • The application’s core and the installed plugin both contribute to the my_app.plugins namespace.

If both app_core and installed_plugins/plugin_a are on the Python path, you can import from both locations seamlessly in main.py:

main.py
import sys

# Add both plugin locations to the path
sys.path.append('./app_core')
sys.path.append('./installed_plugins/plugin_a')

from my_app.plugins import core_plugin
from my_app.plugins import feature_a

core_plugin.run()
feature_a.run()

Python treats my_app.plugins as a single package, combining the contents of all directories found on sys.path. This enables a powerful and decoupled architecture for extensible systems.

The importlib Module

The import statement handles most use cases, but sometimes you need to import modules programmatically. For this, Python provides the built-in importlib library. This is a powerful tool for building dynamic systems, such as plugin architectures or configuration-based module loading.

The most common function you’ll use is importlib.import_module(). It takes the module’s name as a string and returns the imported module object.

Practical Use Cases for importlib

Plugin Architectures

Imagine an application that loads data processors from a plugins directory. The main application doesn’t need to know the names of the plugins in advance.

plugin_manager.py
import os
import importlib

def load_plugins(plugin_dir="plugins"):
    plugins = {}
    for filename in os.listdir(plugin_dir):
        if filename.endswith(".py") and not filename.startswith("__"):
            module_name = filename[:-3]
            # Programmatically import the module
            module = importlib.import_module(f"{plugin_dir}.{module_name}")
            plugins[module_name] = module
            print(f"Loaded plugin: {module_name}")
    return plugins

# Assume a directory 'plugins' with 'csv_processor.py' and 'json_processor.py'
# plugins = load_plugins()
# plugins['csv_processor'].process()

This code scans a directory for Python files, constructs the module path as a string (e.g., "plugins.csv_processor"), and uses importlib.import_module() to load each one.

Dynamic Loading from Configuration

Your application could allow users to specify a component, like an output formatter, in a configuration file.

config.yaml
formatter: "formatters.json_formatter"
main.py
import yaml
import importlib

# Load configuration
with open("config.yaml", "r") as f:
    config = yaml.safe_load(f)

# Get the module path from the config
formatter_path = config.get("formatter")

try:
    # Dynamically import the specified formatter module
    formatter_module = importlib.import_module(formatter_path)
    # Get the format function from the module
    format_data = getattr(formatter_module, "format_data")
    
    # Use the dynamically loaded function
    data = {"key": "value"}
    print(format_data(data))

except (ImportError, AttributeError) as e:
    print(f"Error loading formatter: {e}")

This approach makes your application highly configurable and extensible without requiring code changes to add new formatters.

What are Common Import Patterns and Best Practices?

Once you are comfortable installing and importing modules, following established best practices will make your code more readable, professional, and easier for others to understand. These conventions are recommended by the official PEP 8 style guide and are designed to prevent common issues.

  • Place Imports at the Top: All import statements should be at the very top of your Python file, after any module-level comments or docstrings, but before any code. This gives readers a clear, immediate summary of the file’s dependencies.

  • Group and Order Your Imports: A clean, organized import section is a sign of a well-structured project. The standard convention is to group imports into three blocks, separated by a blank line:

    • Standard Library Imports: Modules that are built into Python (e.g., math, os, sys, json).
    • Third-Party Library Imports: Modules you have installed via pip (e.g., numpy, pandas, requests).
    • Local Application Imports: Modules that are part of your project (e.g., from .utils import helper_function).

    Within each group, it’s best practice to sort the imports alphabetically. This makes it easy to find a specific import and prevents duplicate entries.

    good_imports.py
    
    # 1. Standard library imports
    import json
    import os
    from pathlib import Path
    
    # 2. Third-party imports
    import numpy as np
    import requests
    
    # 3. Local application imports
    from . import my_module
    from .utils import helper_function
    
  • Use Aliases for Clarity and Convention: Use common aliases for well-known libraries to improve readability (e.g., import numpy as np, import pandas as pd). This makes your code more concise while remaining clear to other developers. Avoid creating non-standard aliases (like import numpy as n), as this will confuse other readers who are used to the conventions.

  • Be Specific and Avoid Wildcard Imports: When using the from ... import syntax, import only the specific functions or classes you need. Strongly avoid importing everything with from module import *. This practice, known as a wildcard import, pollutes your global namespace, makes it impossible to know where a function comes from, and can lead to hard-to-debug name clashes.

  • Use Absolute Imports: Whenever possible, prefer absolute imports (from my_package.utils import helper) over relative imports (from ..utils import helper). Absolute imports are more explicit and do not break if you move your script to a different location within the project.

  • Handle Circular Imports and Optional Dependencies: In some advanced cases, you may need to place an import statement somewhere other than the top of the file.

    • Inside a function: If a module is very large and only used in one specific function, importing it locally can speed up the initial load time of your application.
    • To break a circular dependency: If module_a.py imports module_b.py, and module_b.py imports module_a.py, you will get a circular import error. One way to solve this is to move one of the imports inside a function where it’s needed.
    • For optional features: Use a try...except ImportError block to handle optional dependencies. This allows your program to run even if a non-essential library isn’t installed.
  • Use Tools to Automate Formatting: Manually sorting imports can be tedious. Modern Python development relies on tools to do this automatically.

    • isort is a popular utility that automatically sorts and groups your imports according to PEP 8 standards.
    • black is a code formatter that, in addition to styling the rest of your code, also handles import formatting.

Integrating these tools into your workflow ensures your code remains clean and consistent with minimal effort.

Troubleshooting Import Issues

Even when you follow best practices, you will inevitably encounter errors related to importing modules. Understanding what these errors mean is the key to fixing them quickly.

How to Fix ModuleNotFoundError or ImportError: No module named '...' Errors?

This is the most common import-related error. It means Python looked for the module you asked for but could not find it. Here are the usual causes:

  • The module is not installed: You may have forgotten to run pip install <module_name>.
  • A typo in the module name: Check your spelling carefully. For example, import matplotlip instead of import matplotlib.
  • You are in the wrong virtual environment: This is a very common issue. You may have installed the module in your global Python environment, but are running your script from within a virtual environment (or vice-versa). Make sure your terminal is activated in the correct environment where the package was installed.

How to Fix ImportError: cannot import name '...' from '...' Errors?

This error is different. It means Python found the module but could not find the specific function, class, or variable you tried to import from it.

  • A typo in the name: You may have misspelled the function name, e.g., from math import squareroot instead of from math import sqrt.
  • Incorrect case: Names are case-sensitive. from MyModule import MyClass is different from from MyModule import myclass.
  • The name does not exist: The function or class may have been renamed or removed in a newer version of the library, or it may never have existed. Check the library’s official documentation.
  • Circular import: This is a more advanced issue where two modules try to import each other, creating a loop. One module will fail to fully initialize, causing its names to be unavailable.

How to Fix Module Shadowing Errors?

This is a subtle bug that doesn’t always raise an error. It happens when you create a Python file with the same name as a module you want to import.

For example, if you create a file named math.py in your project directory and then try to import math elsewhere in your project, Python will import your local math.py file instead of the built-in standard library module. This will likely cause unexpected behavior or errors.

To avoid this, never name your scripts after existing Python modules, especially common ones from the standard library or popular third-party packages. If you have this issue, simply rename your file.

Using AI to Streamline Python Module Imports

Forgetting a module’s exact name, misspelling it, or not knowing which library to use for a specific task are common roadblocks that disrupt development flow. This is where AI-powered tools can significantly enhance productivity. Modern IDEs and standalone AI assistants can automate and simplify many of the tedious aspects of module management. Let’s explore how AI helps you to achieve this.

Automated Code Completion and Suggestions

One of the most immediate benefits of AI in modern code editors is intelligent code completion. Tools like GitHub Copilot, integrated into IDEs like VS Code, analyze the context of your code in real-time. This goes beyond simple autocompletion by understanding your likely intent based on variable names, comments, and surrounding code logic. When you use a function from a library that hasn’t been imported, the AI suggests the complete code, including the necessary import statement, often adding it to the top of the file for you.

For example, if you begin working with a pandas DataFrame, the AI infers your intent from the conventional pd alias and provides the import.

# You type:
df = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})

# AI automatically suggests:
import pandas as pd

Error Detection and Correction

ImportError and ModuleNotFoundError are two of the most common exceptions in Python. AI tools are adept at identifying and suggesting fixes for these errors, acting as an instant proofreader for your import statements.

This capability is powered by the AI’s training on vast amounts of code, giving it a deep understanding of common library names, popular typos, and correct package structures. When you make a mistake, the AI can often provide a one-click fix. Furthermore, for modules that are missing from your environment, AI-integrated terminals or IDEs can bridge the gap between error and solution by suggesting the precise installation command.

Practical Examples

  • Correcting Typos: A simple misspelling is quickly caught and corrected.

    # Your incorrect code:
    import matplotib.pyplot as plt
    
    # AI Suggestion:
    # Did you mean 'matplotlib'? Change to 'import matplotlib.pyplot as plt'
    
  • Fixing Incorrect Submodule Imports: Sometimes the library name is right, but the path to the function is wrong. The AI understands package structures and can suggest the correct import statement.

    # Your incorrect code:
    from pillow import Image
    
    # AI Suggestion:
    # 'Image' is in the 'PIL' module. Change to 'from PIL import Image'
    
  • Resolving Missing Modules: When a library isn’t installed, the AI provides the command to resolve the ModuleNotFoundError.

    # Your code:
    import seaborn as sns
    
    # IDE/AI Tooltip:
    # ModuleNotFoundError: No module named 'seaborn'.
    # Suggestion: Run 'pip install seaborn' in your terminal.
    

Discovering New Modules and Dependencies

Beyond writing and fixing code, AI excels at the research phase of development. When you face a new problem, you might not know which of the thousands of Python libraries is best suited for the task. Conversational AI assistants like ChatGPT, Google Gemini, or Claude act as a knowledgeable partner, allowing you to describe your goals in natural language and receive tailored recommendations.

This conversational approach is powerful because you can ask follow-up questions, compare libraries, and request code examples for specific use cases. It accelerates discovery and helps you make more informed decisions about your project’s dependencies. For example:

  • Finding a Library for a Specialized Task: You can get nuanced recommendations for complex requirements.

    • Your Prompt: “I need to scrape data from a modern website that loads its content using JavaScript. What Python library should I use instead of just Requests and Beautiful Soup?”
    • AI Response: “For websites that require JavaScript rendering, you should use a browser automation library like Selenium or Playwright. Playwright is more modern and often faster. Here is how you can import it and get started…”
  • Comparing and Contrasting Libraries: You can use the AI to understand the trade-offs between different tools.

    • Your Prompt: “What are the main differences between FastAPI and Flask for building a REST API in Python? Show me the ‘Hello World’ example for each, including imports.”

    • AI Response: “Flask is a minimalist micro-framework, great for simple applications, while FastAPI is a modern, high-performance framework with automatic data validation and API documentation.”

      Flask Example:

      from flask import Flask
      
      app = Flask(__name__)
      
      @app.route('/')
      def hello_world():
        return 'Hello World'
      
      if __name__ == '__main__':
        app.run()
      

      FastAPI Example:

      from fastapi import FastAPI
      
      app = FastAPI()
      @app.get('/')
      
      def read_root():
          return {'message': 'Hello, World!'}
      
  • Discovering Data Visualization Tools: You can find the best tool for a specific type of visualization.

    • Your Prompt: “I’m working in a Jupyter Notebook and need to create an interactive 3D scatter plot. Which Python library is best for this?”
    • AI Response: “For interactive 3D plots in a Jupyter Notebook, Plotly is an excellent choice. It creates rich, interactive visualizations with just a few lines of code. You’ll need to import plotly.express…”

FAQs

1. How do I import a built-in module in Python 3?

You can import a built-in module using the import statement followed by the module’s name. Since these modules come with Python, no installation is needed.

For example, to import the built-in math module, you would write:

import math

2. How can I import a function from a module?

To import a specific function, use the from ... import ... syntax. This brings the function directly into your program’s namespace, so you can call it without using the module name as a prefix.

For example, to import only the sqrt function from the math module:

from math import sqrt

You can then use it directly like this: sqrt(25)

3. Why am I getting a ModuleNotFoundError?

This is a very common error that means Python could not find the module you tried to import. The most common reasons are:

  1. The module is not installed. You need to install it using pip. For example, pip install requests.
  2. A typo in the module name. Double-check that you have spelled the module’s name correctly in your import statement.
  3. You are in the wrong Python environment. You may have installed the module in one environment (like your system’s global Python) but are running your script from a different one (like a virtual environment). Make sure you have activated the correct environment where the module is installed.

4. How to import a copy module in Python?

The copy module is part of Python’s standard library and is used to create shallow and deep copies of objects. You can import it directly:

import copy

You can then use its functions, such as copy.copy() for a shallow copy or copy.deepcopy() for a deep copy.

5. How to install the requests module in Python 3?

You can install the requests module using pip from your command line:

pip install requests

After the installation is complete, you can import it into your Python scripts with: import requests

Conclusion

In this tutorial, we have explored the full spectrum of Python’s import system, from the fundamentals to advanced implementation patterns. You have learned how to install modules with pip, the various syntaxes for importing them, and the best practices for organizing your code. We also covered how to troubleshoot common issues like a ModuleNotFoundError and how to solve complex challenges such as circular dependencies, defining public APIs with __all__, structuring projects with namespace packages, and loading modules dynamically with importlib.

With these skills, you are no longer limited to Python’s built-in functions or simple scripts. You can now confidently create complex applications, design extensible plugin systems, and manage dependencies in large-scale projects. You are well-equipped to explore the vast Python Package Index (PyPI), pull in powerful third-party libraries, and integrate them into your projects with clean, readable, and maintainable code.

With the foundation you’ve built here, check out the following articles to explore modules in more detail:

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

Tutorial Series: How To Code in Python

Python is a flexible and versatile programming language that can be leveraged for many use cases, with strengths in scripting, automation, data analysis, machine learning, and back-end development. It is a great tool for both new learners and experienced developers alike.

About the author(s)

Lisa Tagliaferri
Lisa Tagliaferri
Author
See author profile

Community and Developer Education expert. Former Senior Manager, Community at DigitalOcean. Focused on topics including Ubuntu 22.04, Ubuntu 20.04, Python, Django, and more.

Manikandan Kurup
Manikandan Kurup
Editor
Senior Technical Content Engineer I
See author profile

With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.

Still looking for an answer?

Was this helpful?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Very Nicely and aptly explained. Keep it up .

Thank you for article. It is understandable easily.

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.