Code of the Day
BeginnerPackaging and Sharing

Lab: package and share

Package the CSV extractor utility so it is installable with pip — write pyproject.toml, add an entry point, and test the install locally.

Lab · optionalUtilitiesBeginner20 min
Recommended first
By the end of this lesson you will be able to:
  • Write a complete pyproject.toml for the CSV extractor utility
  • Add a console_scripts entry point that maps a command name to main()
  • Understand the steps to test an editable install locally

This is an optional lab. No new concepts — just the hands-on work of packaging a utility you have already built. The browser runner cannot execute shell commands, so the install steps are a "do it yourself" exercise. The checkpoints test your knowledge of the config file structure.

You have a working CSV extractor in extract.py. In this lab you will write the pyproject.toml that makes it installable, and walk through what a local install looks like step by step.

The goal

After this lab, a collaborator should be able to do this:

git clone https://github.com/you/my-extractor
cd my-extractor
pip install -e .
csv-extract --help

And have a working csv-extract command available in their environment. That is the whole point of packaging: sharing becomes a one-step install.

Step 1 — set up the directory

Create this layout on your machine (or confirm you already have it from the previous lab):

my-extractor/
├── extract.py       (the utility you built)
└── pyproject.toml   (you will write this now)

If you do not have extract.py yet, copy the completed version from the previous lesson. It needs a main() function with an argparse parser, at minimum.

Make sure main() calls parser.parse_args() with no arguments (not the explicit list you used in the browser runner). Without arguments, argparse reads from sys.argv — which is what you want for a real command.

Checkpoint 1 — build-system block

Every modern pyproject.toml starts with a [build-system] block that tells pip which backend to use. For setuptools, it looks like this:

[build-system]
requires = ["setuptools>=61"]
build-backend = "setuptools.backends.legacy:build"

Which field tells pip which backend library to invoke?

Knowledge check

  1. 1.
    In the [build-system] block, which field specifies the build backend?

Step 2 — write the [project] block

Add the project metadata. Fill in the placeholders with real values for your utility:

[project]
name = "csv-extract"
version = "0.1.0"
description = "Extract a named column from CSV input."
requires-python = ">=3.9"

The name field is what pip install uses. Choose something that does not conflict with existing packages on PyPI — prefixing with your username or project name is a safe habit (yourname-csv-extract).

Checkpoint 2 — entry point format

The [project.scripts] section connects a terminal command name to a Python function. The value format is "module:function".

Knowledge check

  1. 1.
    For a file called extract.py with a function called main(), which entry point value is correct?
  2. 2.
    The command name on the left of the = in [project.scripts] must match the Python module filename.

Step 3 — add the entry point

Add this block to your pyproject.toml:

[project.scripts]
csv-extract = "extract:main"

Your complete file should now look like this:

[build-system]
requires = ["setuptools>=61"]
build-backend = "setuptools.backends.legacy:build"

[project]
name = "csv-extract"
version = "0.1.0"
description = "Extract a named column from CSV input."
requires-python = ">=3.9"

[project.scripts]
csv-extract = "extract:main"

Step 4 — install and test

Do it yourself — run these commands in your terminal from the my-extractor/ directory:

# Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

# Install the package in editable mode
pip install -e .

# Confirm the command exists
which csv-extract                  # Windows: where csv-extract

# Test it
echo "name,score,city\nalice,91,london\nbob,74,paris" | csv-extract score

# Expected output:
# score
# 91
# 74

# Test error path
echo "name,score" | csv-extract age
# Should print: error: column not found: age
# And exit with code 1 (check with: echo $?)

When the agent is away: if your shell cannot find csv-extract after installing, confirm the virtual environment is activated (which python should point inside .venv/). If the entry point is wrong, fix pyproject.toml, run pip install -e . again — no need to uninstall first.

Checkpoint 3 — verify understanding

Python — editable, runs in your browser

The key insight: pip does not copy your logic. It creates a tiny script that imports and calls main(). Your code stays in extract.py; the wrapper just knows where to find it. That is why editable installs work — the wrapper always calls the current version of your file.

Done

You have taken a script from "run it in one directory" to "install it and run it anywhere." That is the full arc of this module: from Unix philosophy to working utility to installable tool. Every command-line tool you use daily — black, pytest, httpie, ruff — was built the same way.

Finished reading? Mark it complete to track your progress.

On this page