"Where Python's Collaborative Symphony Begins."
- Introduction
- Creating a Module
import
,from
, andas
if __name__ == "__main__"
- Packages
venv
requests
Pillow
- Choose your direction
- Homework
A Python module is essentially a file that contains definitions and statements.
The module name is the same as the file name with the .py
extension added at the end.
Generally, if we were to write everything into one file, we wouldn't be able to maintain our application, making it hard for other developers to use.
Using modules helps us to do the following:
-
Organizing Code: By dividing a program into modules you can separate parts and concerns making it easier to manage and understand the program.
-
Reusable Components: Functions, classes and variables defined in a module can be easily reused across sections of a program or different programs.
-
Managing Namespaces: Modules help prevent conflicts between names by providing a separate namespace, for each module.
In Python
, a simple .py
file can be considered and used as a module to store specific variables, functions, runnable code or any other object, which can then be used in other modules.
-
Create a Python File: Start by creating a Python file. For instance, name it
mymodule.py
. -
Add Code to the File: Write the necessary functions, classes, and variables in the file. Here’s an example of what
mymodule.py
might look like:
def say_hello(name):
print(f"Hello, {name}!")
def addition(a, b):
return a + b
variable = 123
NOTE: Module names should conform to Python’s naming conventions. They should be short, lowercase, and if necessary, use underscores to improve readability.
Let's create a mini application stored in assets/lesson_12/
directory.
We will split our logic having different .py
files:
└── lesson_12
├── calculations.py
├── greetings.py
├── main.py
└── menu.py
NOTE: Include docstrings and comments to explain what your module does, the purpose of different functions, expected parameter types, return types, and so on.
"""
This modules provides several functions which interact with arithmetical operations between 2 numbers
"""
def add(a, b):
"""Return the sum of a and b."""
return a + b
def subtract(a, b):
"""Return the difference between a and b."""
return a - b
def multiply(a, b):
"""Return the product of a and b."""
return a * b
def divide(a, b):
"""Return the quotient of a divided by b. Raises ValueError on division by zero."""
if b == 0:
raise ValueError("Cannot divide by zero.")
return a / b
Again, instead of having everything in a one file, we created a couple of different files where each serves its purpose.
Break down your application into logical components. Each component should have a well-defined responsibility.
For example, user authentication, data processing, and user interface components can be separate modules.
-
Repeated Code: If you find yourself copying and pasting the same code across multiple parts of your project, it's a sign that you should modularize this code.
-
Reusable Components: If your project contains components that could be reused across different parts of the application or even in different projects, these components are good candidates for modularization.
Don't get stuck or overthink how to do it in the best possible way, everything will come with practice.
Python provides several ways to bring in external modules into your current script, each serves different needs and providing various ways to access the module's components.
Basic Import: Use the import
statement to bring an entire module into your script. This way, you access the module's components using the dot notation, which helps in maintaining their namespace.
import mymodule
mymodule.say_hello("Alice") # Calls the say_hello function from mymodule
result = mymodule.addition(10, 20) # Calls the addition function from mymodule
print(mymodule.variable) # Access the variable from mymodule
Import Specific Components: You can choose to import specific components (functions, classes, or variables) from a module. This is useful when you only need a part of the module.
from mymodule import say_hello, addition
say_hello("Bob") # Directly use the imported function
result = addition(5, 15) # Directly use the imported function
Note: Generally, it is a preferable way, as very often we don't need to import everything
Importing All Components: Using from module import *
imports all public names from the module into the current namespace.
from mymodule import *
NOTE: It's generally discouraged as it can lead to conflicts with existing names and makes it unclear which names are present in the current namespace.
Aliasing Modules: If a module name is long or likely to conflict with an existing name in your code, you can give it an alias. This allows you to reference it with a different name.
import mymodule as mm
mm.say_hello("Carol") # Use the alias to call a function from mymodule
Aliasing Specific Components: You can also alias specific components when you import them.
from mymodule import say_hello as greet
greet("Dave") # Use the alias to call the imported function
For example, let's say you are trying to import a function time
from two different modules.
The only way you can achieve this without causing conflicts within the code is by using aliasing.
from x import time as x_time
from y import time as y_time
Thanks to as
you can use time
from both x
and y
modules, without any conflicts and be able to distinct them too.
When writing Python scripts, you'll often see a code block guarded by at the bottom:
if __name__ == "__main__"
The special __name__
attribute is set to __main__
when a script is executed directly.
However, when the same script is imported as a module in another script, __name__
is set to the script's filename.
Consider the script mymodule.py
, which defines a function and is executed:
# mymodule.py
def say_hello(name):
"""Print a greeting to the named individual."""
print(f"Hello, {name}!")
def main():
"""Run the main logic of the script."""
say_hello("Alice")
# This condition checks if the script is the entry point to the program
if __name__ == "__main__":
main() # Only runs if the script is executed, not if it's imported.
If mymodule.py
is run as the main file, the main()
function will execute and Alice
will be greeted.
If mymodule.py
is imported into another file, say_hello
can be used, but Alice
will not be greeted until say_hello
is explicitly called.
Try it yourself and experiment with the code provided in assets/lesson_12
, and you will see the diference.
Packages allow you to group related modules under a common namespace, making it easier to understand and manage the code.
They help in avoiding conflicts between module names and provide a structured way to access the functions, classes, and variables defined in different modules.
The __init__.py
file is a key ingredient in Python packages. It serves multiple roles:
- Initialization: Executes any code necessary to set up the package's state or initialize certain variables.
- Namespace Management: Declares which modules or symbols the package exports as the API, through
__all__
. - Hierarchy Signaling: Signifies to Python that the directory should be treated as a package, allowing modules to be imported from it.
Instead of raw theory, let's take a look at the real application and try to come up with a good structure for better maintainability of the codebase
Consider a package named finance
designed to handle various financial calculations and data processing
Strucure
finance/
__init__.py
calculator.py
taxes.py
investments/
__init__.py
stocks.py
bonds.py
finance/__init__.py
# Specify the public API for convenience
__all__ = ['calculator', 'taxes', 'investments']
# You may also initialize some package-wide constants or setup code, though its not a common practice nowdays
DEFAULT_TAX_BRACKET = '25%'
finance/calculator.py
def calculate_interest(principal, rate, time):
"""Compute interest earned on a principal over time at a fixed rate."""
return principal * (rate / 100) * time
finance/taxes.py
from .calculator import calculate_interest
def calculate_tax_due(income, rate=DEFAULT_TAX_BRACKET):
"""Calculate the tax owed based on income and a tax rate."""
pass
finance/investments/stocks.py
def analyze_stock_market():
"""Perform analysis on stock market trends."""
pass
Sub-packages enable even more granular organization within a package, grouping together related modules.
For instance, finance/investments
is a sub-package grouping financial investment-related modules like stocks.py
and bonds.py
.
When the project becomes extremely big, think about how you could re-structure to make it more maintainable, reusable and readable.
Importing from packages or sub-packages is done with a .dot
notation, allowing you to use specific functions or entire modules.
Examples:
# Importing a specific function from a module within the 'finance' package
from finance.calculator import calculate_interest
# Importing an entire module from a sub-package
from finance.investments import stocks
# Using the imported function
interest = calculate_interest(1000, 5, 3) # Calculate interest on $1000 at 5% for 3 years
# Invoking a function from the imported 'stocks' module
stocks.analyze_stock_market()
Python’s virtual environments allow you to install and manage Python packages in an isolated environment.
Suppose we need to install a couple of external packages, which provide interfaces to carry out some specific tasks and resolve issues while it can't be done with a default Python functionality.
That's where virtual environments and external packages come in handy.
- Dependency Management: Keep project-specific dependencies in separate environments.
- Project Isolation: Avoid installing packages globally, which can lead to version conflicts.
- Reproducibility: Create an environment that can easily be replicated on other machines or deployments.
The purpose of venv is to ensure that each project has its own set of dependencies, which may differ in version from one project to another, without causing conflicts.
IMPORTANT: We could install everything globally, but such behaviour leads to conflicts among projects, and is not recomended at all.
You can create a virtual environment using the venv
module that comes with Python 3.x.
-
Setup: Navigate to your project’s directory:
cd my_project
-
Creation: Run the following command to create a virtual environment named
venv
:python3 -m venv venv
Note: You can replace venv
with your preferred environment name.
- Activation: Run the following commands
-
On Windows:
.\venv\Scripts\activate
-
On macOS and Linux:
source venv/bin/activate
When activated, the name of the virtual environment (venv
) will appear in your shell prompt, indicating that all python
and pip
commands are now scoped to the venv
.
NOTE: Create a new virtual environment for each project to keep dependencies separate.
With an activated virtual environment, you can use pip
to install, upgrade, and remove packages. Essentially, pip
is a package manager which helps you to install the external dependencies from PyPi.
- Installing Packages:
pip install package_name
- Listing Installed Packages:
pip list
- Uninstalling Packages:
pip uninstall package_name
As well, you can run pip --help
if you want to do anything other with venv
inside your project.
Let's take a look at the couple of interesting modules in the sections below.
The requests
module is a Python HTTP library that simplifies making network requests. It’s known for its ease of use and user-friendly interface.
Before you can use requests
, you'll need to create venv
, activate and install requests
into it.
python3 -m venv venv
source venv/bin/activate
pip install requests
Let's create an application and split everything into diffrent modules as it was already discussed above.
Objective:: Develop an application to display real-time weather information based on user input.
NOTE: The application will interact with the OpenWeatherMap
API
to obtain data for the specified city and present it to the user in a clear and concise format.
weather_fetcher/
├── fetch.py
├── display.py
├── main.py
└── constants.py
constants.py
# Store configuration constants
BASE_URL = "http://api.openweathermap.org/data/2.5/weather"
API_KEY = "your_api_key_here" # Replace with your actual OpenWeatherMap API key
fetch.py
# Contains the logic for fetching weather data from OpenWeatherMap API
import requests
from .constants import BASE_URL, API_KEY # Ensure proper relative import
def get_weather_data(city):
"""Fetch weather data for a given city."""
params = {
'q': city,
'appid': API_KEY,
'units': 'metric'
}
response = requests.get(BASE_URL, params=params)
if response.status_code == 200:
return response.json()
else:
response.raise_for_status()
display.py
# Contains the logic for displaying the fetched weather data
def display_weather(data):
"""Display the weather information."""
city = data['name']
temp = data['main']['temp']
description = data['weather'][0]['description']
humidity = data['main']['humidity']
print(f"Weather in {city}:")
print(f"Temperature: {temp}°C")
print(f"Condition: {description}")
print(f"Humidity: {humidity}%")
main.py
# Entry point for the Weather Fetcher application
from fetch import get_weather_data
from display import display_weather
def main():
city = input("Enter the name of the city to get the weather for: ")
try:
weather_data = get_weather_data(city)
display_weather(weather_data)
except requests.exceptions.HTTPError as err:
print("HTTP error occurred: ", err)
except requests.exceptions.RequestException as err:
print("Request error occurred: ", err)
if __name__ == "__main__":
main()
You can find the whole project in assets/weather_fetcher
directory.
Pillow is a fork of the Python Imaging Library (PIL) which adds image processing capabilities to your Python interpreter.
Install the library in your virtual environment, same as we did with requests
library:
python3 -m venv venv
source venv/bin/activate
pip install Pillow
Objective: Develop an application will perform basic operations on an image, such as opening, displaying, rotating, and cropping.
image_processor/
├── processor.py
└── main.py
processor.py
from PIL import Image
def open_image(path):
"""Open and return an image."""
return Image.open(path)
def show_image(image):
"""Display the image."""
image.show()
def rotate_image(image, degrees):
"""Rotate the image by a certain number of degrees."""
return image.rotate(degrees)
def crop_image(image, box):
"""Crop the image to a specific box and return the cropped image."""
return image.crop(box)
main.py
from processor import open_image, show_image, rotate_image, crop_image
def main():
image_path = input("Enter the path to the image: ")
image = open_image(image_path)
show_image(image)
rotated = rotate_image(image, 90)
show_image(rotated)
cropped = crop_image(image, (100, 100, 400, 400))
show_image(cropped)
if __name__ == "__main__":
main()
You can find the whole project in assets/image_processor
directory.
Add functionality for saving image and applying filters and effects to it.
It's time that you decide your career path and who you want to become in the future. Now you have a general idea about programming and you need to research more information and decide the future direction of your career.
I can recommend a several libraries to look into for Data Science
and Web Development
.
- Pandas: Data manipulation and analysis.
- NumPy: Numerical computing with powerful array objects.
- Matplotlib & Seaborn: Data visualization.
- Scikit-learn: Machine learning.
- TensorFlow & PyTorch: Deep learning.
- Django & Flask: Web frameworks for building web applications.
- FastAPI: Modern, fast web framework for building APIs.
- SQLAlchemy: Database toolkit and ORM.
- Celery: Asynchronous task queue/job queue.
- Redis & Memcached: Caching systems to enhance performance.
Thanks for attention! Happy Restructuring!
During this howemork I would like you to google. It's an extremely important skill for a programmer, which we use on a daily basis.
Disclaimer: Sometimes people can give you tasks which you don't know how to accomplish, there are a couple of unknown words (libs) below. Good luck!
Objective: Build a Python application that generates an HTML image gallery from a folder of image files.
Requirements:
- Create a virtual environment and install
Pillow
for image processing. - Create a module to resize images to thumbnails using Pillow.
- Ensure images maintain their aspect ratio.
- Write a module to generate an HTML file that displays all thumbnails as clickable links to the original images.
- Implement a command-line interface where the user can specify the folder containing images and the output directory for the HTML gallery.
Objective: Create a command-line interface (CLI) task manager application that allows users to add, list, and delete tasks.
Requirements:
- Create a virtual environment and install
Pillow
for image processing. - Enable users to add new tasks, mark tasks as completed, list all tasks, and delete tasks through command-line arguments.
- Use the
argparse
orclick
library to handle command-line arguments for different operations (e.g.,--add
,--complete
,--list
,--delete
).