Packaging and distribution let you turn Python scripts into something that can be installed, shared, or even executed as standalone applications. This lesson begins with virtual environments, then shows how to turn Python files into EXE executables, and finally explores modern packaging tools like pyproject.toml, setuptools, and installations using pip.
1) Virtual Environments (venv)
A virtual environment is an isolated Python workspace where you install packages without affecting your system Python. Each project should have its own venv so dependencies don’t conflict between projects.
Create a virtual environment
python -m venv venv
Activate the virtual environment
Windows:
venv\Scripts\activate
macOS / Linux:
source venv/bin/activate
After activation, your terminal prompt will show (venv), and all pip install commands will install packages inside this environment only.
Upgrade pip (recommended)
pip install --upgrade pip
Install packages inside the virtual environment
pip install numpy pandas requests
Freeze installed packages (pip freeze)
This command lists all installed dependencies along with their exact versions. You use it to create a requirements.txt file.
pip freeze
To save the list into a requirements file:
pip freeze > requirements.txt
Now your project has a snapshot of exact package versions, which is important for deployment and sharing your code with others.
Install dependencies from requirements.txt
When someone downloads your project (or you deploy it on a server), they can install everything with one command:
pip install -r requirements.txt
Deactivate the virtual environment
deactivate
Check which Python interpreter is being used
which python # macOS / Linux
where python # Windows
Inside venv, these commands should point to the venv folder, confirming the environment is active.
Remove a virtual environment
To delete a venv, simply remove the folder:
rm -rf venv # macOS / Linux
rmdir /s venv # Windows
The environment will be recreated when needed.
Best Practices for Virtual Environments
- Create one venv per project
- Always activate venv before installing packages
- Use requirements.txt for sharing and deployment
- Do not commit
venv/to version control (add to.gitignore) - Upgrade pip regularly for compatibility
- Use meaningful names like
.venv,env, orvenv
With this setup, your project stays organized, reproducible, and easy to share or deploy.
2) Creating an EXE File from a Python Script
Sometimes you need to distribute your program to users who do not have Python installed. Tools like PyInstaller allow you to convert a Python script into a standalone executable (.exe on Windows).
Install PyInstaller
pip install pyinstaller
Create an EXE
pyinstaller --onefile your_script.py
PyInstaller will generate a dist/ folder containing your .exe file. Pass that file to anyone — no Python installation required.
Common options
pyinstaller --onefile --windowed app.py
pyinstaller --onefile --icon=app.ico app.py
Use --windowed for GUI applications (no console), and --icon to add an application icon.
3) Why Packaging Matters
Packaging helps you turn normal Python code into a reusable, installable, and maintainable project. This applies to CLI apps, internal libraries, automation tools, or public open-source packages.
- Dependencies stay clean and isolated
- Your code becomes installable with
pip - You can distribute wheels or publish to PyPI
- Users get predictable, stable installation workflows
4) Recommended Project Layout
myproject/
│
├── src/
│ └── myproject/
│ ├── __init__.py
│ └── main.py
│
├── tests/
│ └── test_main.py
│
├── pyproject.toml
├── README.md
└── LICENSE
This “src layout” is now the modern Python standard.
Purpose of each part
src/myproject/— your package code__init__.py— marks the folder as a Python packagepyproject.toml— package metadata & build settingstests/— unit testsREADME.md— documentation
5) pyproject.toml — Modern Python Packaging
This file replaces the old setup.py. It contains all the metadata required to build and install your package. It is clean, simple, and the recommended format.
Basic pyproject.toml example
[project]
name = "myproject"
version = "0.1.0"
description = "A sample Python package"
authors = [
{ name="Ammar", email="[email protected]" }
]
dependencies = [
"requests",
]
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
The [project] section describes your package. The [build-system] section tells Python which tool to use to build it.
6) Writing Your Package Code
src/myproject/main.py:
def greet(name):
return f"Hello, {name}!"
src/myproject/__init__.py:
from .main import greet
7) Building Your Package
First install the build tool:
pip install build
Build:
python -m build
This generates:
- .whl — wheel file (fast installable package)
- .tar.gz — source package
8) Installing Your Package Using pip
You can install the package locally for testing:
pip install dist/myproject-0.1.0-py3-none-any.whl
Now import it anywhere:
import myproject
print(myproject.greet("Ammar"))
9) setuptools — Build Backend Explained
setuptools is the engine behind most Python packages. It handles:
- Installing dependencies
- Building wheels
- Defining command-line tools
- Reading metadata from
pyproject.toml
Adding a console script (CLI command)
Add this inside pyproject.toml:
[project.scripts]
mytool = "myproject.main:greet"
Now users can run:
mytool
10) (Optional) Publishing to PyPI
If you want people to install your package using pip install myproject:
pip install twine
twine upload dist/*
Once uploaded, anyone can install your package globally:
pip install myproject
11) Summary
- Create a venv to isolate your project
- Convert scripts into EXE using PyInstaller
- Use the src-layout for clean packaging
- Store metadata in pyproject.toml
- Build with
python -m build - Install locally using
pip install dist/*.whl - Publish with Twine if needed
Leave a comment
Your email address will not be published. Required fields are marked *
