Post

Python Poetry: A Complete Guide

Python Poetry: A Complete Guide

Python Poetry: A Complete Guide for Users and Creators

Poetry is a modern dependency management and packaging tool for Python that simplifies project setup, dependency management, and distribution. This guide covers Poetry from two perspectives: as a user working with existing projects, and as a creator building new ones.

Table of Contents


Quick Start: For Users

If you’re contributing to an existing Poetry project, follow these steps to get started quickly.

1. Install Poetry

First, install Poetry on your system:

1
2
curl -sSL https://install.python-poetry.org | python3 -
poetry --version

2. Clone and Setup the Project

1
2
3
4
5
6
7
8
9
# Clone the repository
git clone <repository-url>
cd project

# Configure Poetry to create virtual environment in project directory
poetry config virtualenvs.in-project true

# Install all dependencies from poetry.lock
poetry install

That’s it! Poetry will:

  • Read the pyproject.toml and poetry.lock files
  • Create a virtual environment (.venv/)
  • Install all dependencies with exact versions

3. Working with the Project

run commands directly:

1
2
3
poetry run python main.py
poetry run pytest
poetry run python -m mypackage.main

4. Managing Dependencies

View installed packages:

1
2
3
poetry show              # List all packages
poetry show --tree       # Show dependency tree
poetry show requests     # Show details for specific package

Update dependencies:

1
2
poetry update            # Update all packages
poetry update requests   # Update specific package

5. Common User Commands

1
2
3
4
poetry env info          # Show environment information
poetry env list          # List all virtual environments
poetry lock              # Update poetry.lock without installing
poetry check             # Validate pyproject.toml

Complete Guide: For Creators

Creating a new project with Poetry requires more initial setup, but provides better long-term project management.

Prerequisites

Before creating a Poetry project, set up your Python environment properly.

1. Install System Dependencies

Install build dependencies for Python:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo apt update
sudo apt install -y \
  build-essential \
  libssl-dev \
  zlib1g-dev \
  libbz2-dev \
  libreadline-dev \
  libsqlite3-dev \
  libffi-dev \
  liblzma-dev \
  xz-utils \
  tk-dev \
  libncursesw5-dev \
  libgdbm-dev \
  libnss3-dev \
  uuid-dev

2. Install pyenv

pyenv allows you to manage multiple Python versions:

1
curl https://pyenv.run | bash

Important: Add pyenv to your shell:

1
2
3
4
# Add to ~/.bashrc or ~/.zshrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

Then reload your shell:

1
exec $SHELL

3. Install Python Version

1
2
pyenv install 3.10.5
pyenv versions           # List installed versions

Note: Poetry requires Python >= 3.9. Use pyenv to install a compatible version if needed.

Installing Poetry

Ensure you’re using system Python before installing Poetry:

1
2
3
pyenv shell --unset
pyenv global system
poetry --version

If Poetry isn’t installed:

1
2
curl -sSL https://install.python-poetry.org | python3 -
poetry --version

Configuring Poetry

Configure Poetry to create virtual environments in your project directory:

1
poetry config virtualenvs.in-project true

This creates .venv/ folders in each project, making them easier to manage and exclude from version control.

Creating a New Project

Poetry offers two ways to start a project:

Option 1: Initialize in Existing Directory

1
2
3
cd ~/my_project
pyenv local 3.10.5      # Set Python version for this project
poetry init             # Interactive setup wizard

The poetry init command will ask you:

  • Project name
  • Version
  • Description
  • Author
  • License
  • Compatible Python versions
  • Dependencies to add

Option 2: Create New Project with Structure

Poetry can scaffold a complete project structure:

1
2
3
4
5
6
# Update Poetry first
poetry self update

# Create new project
cd ~/repos
poetry new --src my_project --name my_package

Key Options:

  • --src: Creates a src/ directory layout (recommended for packaging)
  • --name my_package: Names the package differently from the project directory

Generated structure:

1
2
3
4
5
6
7
8
9
my_project/
├── pyproject.toml
├── README.rst
├── src/
│   └── my_package/
│       └── __init__.py
└── tests/
    ├── __init__.py
    └── test_my_package.py

Configuring Your Project

1. Set Python Version

Tell Poetry which Python version to use:

1
2
3
cd my_project
pyenv local 3.10.5
poetry env use $(pyenv which python)

2. Configure Package Location (if using src layout)

If you used --src, add this to pyproject.toml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[tool.poetry]
name = "my_package"
version = "0.1.0"
description = "My awesome package"
authors = ["Your Name <you@example.com>"]

packages = [
    { include = "my_package", from = "src" }
]

[tool.poetry.dependencies]
python = "^3.10"

[tool.poetry.group.dev.dependencies]
pytest = "^7.0"

3. Install Dependencies

1
poetry install

This creates the virtual environment and installs dependencies.

Managing Dependencies

Adding Packages

1
2
3
4
5
6
7
8
# Production dependency
poetry add requests
poetry add numpy==1.26.4        # Specific version
poetry add "django>=4.0,<5.0"   # Version range

# Development dependency
poetry add --group dev pytest
poetry add --group dev black mypy ruff

Removing Packages

1
2
poetry remove requests
poetry remove --group dev pytest

Organizing Dependencies

Use dependency groups for different purposes:

1
2
3
4
5
6
[tool.poetry.group.dev.dependencies]
pytest = "^7.0"
black = "^23.0"

[tool.poetry.group.docs.dependencies]
sphinx = "^5.0"

Install specific groups:

1
2
poetry install --with docs
poetry install --without dev

Running Your Project

Example Project Structure

Let’s create a simple example:

1
2
3
4
5
6
7
8
9
10
11
12
13
# src/my_package/__init__.py
__version__ = "0.1.0"

# src/my_package/main.py
import numpy as np

def main():
    arr = np.array([1, 2, 3])
    print(f"Array: {arr}")
    print(f"Mean: {arr.mean()}")

if __name__ == "__main__":
    main()

Running the Code

1
2
3
4
5
6
7
8
# Activate environment
poetry shell

# Run as module
python -m my_package.main

# Or run directly without activation
poetry run python -m my_package.main

Example output:

1
2
3
4
5
6
7
8
9
10
11
12
$ poetry add numpy==1.26.4
Updating dependencies
Resolving dependencies... (0.5s)

Package operations: 1 install, 0 updates, 0 removals
  - Installing numpy (1.26.4)

Writing lock file

$ poetry run python -m my_package.main
Array: [1 2 3]
Mean: 2.0

Building and Publishing

Build Your Package

1
poetry build

This creates distribution files in dist/:

  • my_package-0.1.0-py3-none-any.whl (wheel)
  • my_package-0.1.0.tar.gz (source distribution)

Publish to PyPI

1
2
3
4
5
# Configure PyPI credentials (once)
poetry config pypi-token.pypi your-api-token

# Publish
poetry publish

Or build and publish together:

1
poetry publish --build

Common Workflows

Workflow 1: Daily Development

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Start your session
cd my_project
poetry shell

# Make changes to code...

# Run tests
pytest

# Format code
black .

# Run your application
python -m my_package.main

Workflow 2: Adding a New Feature

1
2
3
4
5
6
7
8
9
10
11
12
# Install new dependency
poetry add rich

# Update code to use it
# ...

# Test locally
poetry run pytest

# Commit changes (including poetry.lock)
git add pyproject.toml poetry.lock
git commit -m "Add rich for better output"

Workflow 3: Updating Dependencies

1
2
3
4
5
6
7
8
9
10
11
12
# Check for outdated packages
poetry show --outdated

# Update specific package
poetry update requests

# Update all packages
poetry update

# Commit the updated lock file
git add poetry.lock
git commit -m "Update dependencies"

Workflow 4: Exporting Requirements

For compatibility with non-Poetry tools:

1
2
3
4
5
6
7
8
# Export production dependencies
poetry export -f requirements.txt --output requirements.txt

# Export with dev dependencies
poetry export -f requirements.txt --output requirements.txt --with dev

# Without hashes (cleaner file)
poetry export -f requirements.txt --output requirements.txt --without-hashes

Best Practices

For Users and Creators

  1. Always commit poetry.lock
    • Ensures everyone uses identical dependency versions
    • Prevents “works on my machine” issues
  2. Use .gitignore properly
    .venv/
    *.pyc
    __pycache__/
    dist/
    *.egg-info/
    
  3. Keep Poetry updated
    1
    
    poetry self update
    
  4. Use dependency groups
    • Separate dev, test, and docs dependencies
    • Keeps production installations lean
  5. Pin Python versions appropriately
    1
    2
    3
    4
    
    [tool.poetry.dependencies]
    python = "^3.10"  # Allows 3.10, 3.11, 3.12, etc.
    # Or be more specific
    python = ">=3.10,<3.13"
    

For Creators

  1. Use the src/ layout
    • Prevents import confusion
    • Better for packaging
    • Enforces proper installation
  2. Document your project
    • Keep README.md updated
    • Document development setup
    • Include example usage
  3. Set up pre-commit hooks
    1
    2
    
    poetry add --group dev pre-commit
    poetry run pre-commit install
    
  4. Configure your IDE
    • Point VS Code/PyCharm to Poetry’s virtual environment
    • Both have built-in Poetry support
  5. Use semantic versioning
    • Follow semver.org
    • Use poetry version to bump versions
      1
      2
      3
      
      poetry version patch  # 0.1.0 -> 0.1.1
      poetry version minor  # 0.1.1 -> 0.2.0
      poetry version major  # 0.2.0 -> 1.0.0
      

Useful Commands Reference

Environment Management

1
2
3
4
poetry env use python3.10        # Use specific Python version
poetry env info                  # Show environment details
poetry env list                  # List all environments
poetry env remove python3.10     # Remove environment

Dependency Management

1
2
3
4
5
6
7
8
poetry add package               # Add dependency
poetry add --group dev package   # Add dev dependency
poetry remove package            # Remove dependency
poetry update                    # Update all dependencies
poetry update package            # Update specific package
poetry show                      # List installed packages
poetry show --tree               # Show dependency tree
poetry show --outdated           # Show outdated packages

Project Management

1
2
3
4
5
6
7
8
poetry init                      # Initialize new project
poetry install                   # Install dependencies
poetry install --no-dev          # Install without dev dependencies
poetry install --with docs       # Install with optional group
poetry lock                      # Update lock file
poetry check                     # Validate pyproject.toml
poetry build                     # Build distributions
poetry publish                   # Publish to PyPI

Running Code

1
2
3
poetry run python script.py      # Run Python script
poetry run pytest                # Run tests
poetry shell                     # Activate virtual environment

Troubleshooting

Issue: Poetry can’t find Python version

1
2
3
4
5
# Make sure Python is installed
pyenv versions

# Set it explicitly
poetry env use $(pyenv which python)

Issue: Dependencies not resolving

1
2
3
4
# Clear cache and retry
poetry cache clear pypi --all
poetry lock --no-update
poetry install

Issue: Virtual environment in wrong location

1
2
3
4
5
6
7
8
9
# Check current setting
poetry config virtualenvs.in-project

# Set it to true
poetry config virtualenvs.in-project true

# Remove old environment and recreate
poetry env remove python
poetry install

Conclusion

Poetry simplifies Python project management for both users and creators:

As a User:

  • Quick setup: poetry install
  • Consistent environments via poetry.lock
  • Simple dependency updates

As a Creator:

  • Professional project structure
  • Easy dependency management
  • Simplified packaging and publishing
  • Better collaboration through locked dependencies

Whether you’re contributing to open source or building your own projects, Poetry provides the tools to manage Python dependencies effectively.

Additional Resources


This post is licensed under CC BY 4.0 by the author.