Language:

Search

Python Packaging & Distribution Guide: Virtual Environments, pyproject.toml, setuptools & pip

Python Packaging & Distribution Guide: Virtual Environments, pyproject.toml, setuptools & pip

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, or venv

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 package
  • pyproject.toml — package metadata & build settings
  • tests/ — unit tests
  • README.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
Ahmad Ali

Ahmad Ali

Leave a comment

Your email address will not be published. Required fields are marked *

Your experience on this site will be improved by allowing cookies Cookie Policy