By Lisa Tagliaferri and Manikandan Kurup
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:
.py
file, a package is a directory of modules, and a library is a collection of packages that provide specific functionality.pip install <module_name>
command to download and install third-party packages from the Python Package Index (PyPI).import module_name
syntax to keep code clear and avoid namespace conflicts; always avoid wildcard imports (from module import *
).sys.path
, starting with the current script’s directory.__all__
variable to explicitly define the public API of a module that gets imported during a wildcard import.importlib
module to import modules programmatically using their string names, enabling dynamic code loading.ModuleNotFoundError
by checking if the module is installed and spelled correctly, and an ImportError
by verifying the function’s name.Before you begin, ensure you have the following prerequisites:
If you need help setting up your environment, refer to these tutorials:
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:
While often used interchangeably, “module”, “package”, and “library” have distinct meanings within the Python ecosystem:
.py
file containing Python code. When you import a module, you bring its definitions and statements into your current script’s namespace.__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.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.
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.
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.
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.
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.
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.
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.
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.
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:
OutputThe 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.
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:
math.sqrt()
is far clearer than code that just uses sqrt()
.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.
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.
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.
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:
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.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.
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']
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.
# 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.
# 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.
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.
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.
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)
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)
Resolving circular imports usually involves rethinking your application’s structure to remove the circular dependency.
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.
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:
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.
TYPE_CHECKING
for Type HintsIf 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.
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.
__all__
VariableWhen 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.
__all__
Consider a module that provides utility functions but also has some internal helpers.
# 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.
__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.
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:
my_app
nor my_app/plugins
contains an __init__.py
file.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
:
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.
importlib
ModuleThe 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.
importlib
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.
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.
Your application could allow users to specify a component, like an output formatter, in a configuration file.
formatter: "formatters.json_formatter"
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.
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:
math
, os
, sys
, json
).pip
(e.g., numpy
, pandas
, requests
).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.
# 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.
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.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.
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.
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:
pip install <module_name>
.import matplotlip
instead of import matplotlib
.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.
from math import squareroot
instead of from math import sqrt
.from MyModule import MyClass
is different from from MyModule import myclass
.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.
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.
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
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.
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.
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.
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.
plotly.express
…”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
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)
ModuleNotFoundError
?This is a very common error that means Python could not find the module you tried to import. The most common reasons are:
pip
. For example, pip install requests
.import
statement.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.
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
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.
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.
Browse Series: 36 tutorials
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.
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.
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!
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.