0Pricing
Python Academy · Lesson

Project Structure and pyproject.toml

Lay out a package.

Project Structure and pyproject.toml is a free Python Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Package Your Code

A script lives on your machine; a package can be installed by anyone with pip install. Packaging turns a folder of code into a distributable, versioned, reusable unit.

The first step is a clean project layout and a configuration file.

The src Layout

The recommended structure puts your importable code under a src/ directory:

  • src/mypackage/__init__.py
  • src/mypackage/core.py
  • pyproject.toml
  • README.md and tests/

The src layout prevents accidentally importing your code from the project root instead of the installed copy.

The __init__.py File

__init__.py marks a directory as an importable package and runs when the package is first imported. It is also where you expose the public API by importing key names.

Even an empty __init__.py is enough to make a package.

package_dir = 'src/mypackage'
files = ['__init__.py', 'core.py', 'utils.py']
for f in files:
    print(package_dir + '/' + f)
print('Importable as:', 'mypackage')

What pyproject.toml Is

pyproject.toml is the single, standardized config file (PEP 518/621) for modern Python packaging. It replaces the old setup.py for most projects and is read by build tools.

It uses the TOML format: sections in square brackets and key = value lines.

The build-system Table

The [build-system] table tells tools how to build your package. A common choice:

  • requires = ['setuptools', 'wheel']
  • build-backend = 'setuptools.build_meta'

Other backends include Hatchling and Flit; the idea is the same.

The project Table

The [project] table holds metadata: name, version, description, authors, readme, requires-python, and dependencies. This is what users see on PyPI.

Think of it as the identity card of your package.

project = {
    'name': 'mytool',
    'version': '0.1.0',
    'requires-python': '>=3.9',
    'dependencies': ['requests>=2.0'],
}
for k, v in project.items():
    print(k, '=', v)

Naming Rules

The package name must be unique on PyPI and follows normalization: case-insensitive, with hyphens and underscores treated the same. Check availability before settling on a name to avoid a clash at upload time.

name = 'My_Cool.Tool'
normalized = name.lower().replace('_', '-').replace('.', '-')
print('PyPI normalized name:', normalized)

Declaring Dependencies

List runtime dependencies under dependencies with version constraints like 'requests>=2.28,<3'. Optional extras go under [project.optional-dependencies], installable via pip install mytool[dev].

Keep constraints as loose as is safe so your package coexists with others.

Entry Points

To ship a command-line tool, add a [project.scripts] entry like mytool = 'mypackage.cli:main'. After install, typing mytool runs that function. This is how CLIs like black or pytest expose their commands.

Including Non-Code Files

Data files (templates, JSON) are not included automatically. Configure package data in your build backend so files ship inside the wheel. Forgetting this is a common cause of works-locally-but-breaks-when-installed bugs.

Editable Installs for Development

While developing, install your package in editable mode with pip install -e .. Changes to the source take effect immediately without reinstalling. This relies on a correct pyproject.toml, which is another reason to set it up early.

Editable installs are the fastest feedback loop while iterating on a package.

Quick Check

Test your project structure knowledge.

Recap

You laid out a package:

  • Use the src layout with __init__.py marking packages
  • pyproject.toml is the standard config: [build-system] and [project]
  • Declare name, version, requires-python, and dependencies
  • Add [project.scripts] entry points for CLIs and configure package data

Frequently asked questions

Is the “Project Structure and pyproject.toml” lesson free?

Yes — the full text of “Project Structure and pyproject.toml” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.

What will I learn in “Project Structure and pyproject.toml”?

Lay out a package. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Python Academy?

No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Project Structure and pyproject.toml” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Python Academy lesson?

Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Project Structure and pyproject.toml
  2. Building with build
  3. Versioning and Metadata
  4. Publishing with twine
← Back to Python Academy