# Getting Started with Poetry

[Poetry](https://python-poetry.org/) is a modern dependency management and packaging tool for Python that simplifies project setup, dependency resolution, and package distribution. It creates a smooth workflow that handles virtual environments, package installations, and project scaffolding in one cohesive toolchain.

This article will guide you through Poetry's essential features, explain its benefits over traditional tools, and demonstrate how to optimize your Python development workflow.

[ad-logs]

## Prerequisites

Before exploring Poetry, ensure you have a recent version of [Python](https://www.python.org/downloads/) installed on your system, which is Python 3.13 or higher. You should also know concepts like virtual environments and basic Python package management.

## Why use Poetry?

Before diving into Poetry, let's understand why it significantly improves over traditional Python package management approaches. Here's what makes Poetry unique:

- Unified dependency management: While `pip` requires separate tools for environments and lockfiles, Poetry handles dependencies, virtual environments, and package publishing in a single tool
- Deterministic builds: Poetry uses a sophisticated dependency resolver that creates lockfiles ensuring identical environments across different machines
- Project isolation: Poetry automatically manages virtual environments, eliminating the manual `venv` activation and deactivation process
- Modern packaging standards: Poetry embraces `pyproject.toml` as the configuration standard, replacing outdated `setup.py` and requirements files with a cleaner, more structured approach

Think of Poetry as an all-in-one solution that combines the functionality of pip, virtualenv, and setuptools while adding powerful features like dependency resolution and lockfile generation.

Throughout this tutorial, you'll discover how these features work together to simplify your Python workflow and make package management more reliable.

## Installing Poetry

In this section, you will install Poetry on your machine.

While Poetry requires Python to work, it manages Python projects independently of your system Python. To verify you have Python installed, run:

```command
python3 --version
```

You should see output similar to:

```command
Python 3.13.2
```

The recommended method to install Poetry is through its official installer script:

```command
curl -sSL https://install.python-poetry.org | python3 -
```

This command will download and install Poetry to `~/.local/bin` by default on Unix-based systems.

You can verify the successful installation by executing:

```command
poetry --version
```

```text
[output]
Poetry (version 2.1.1)
```

If the `poetry` command isn't recognized, add Poetry to your PATH with:

```command
export PATH="$HOME/.local/bin:$PATH"
```

This output confirms that Poetry is installed correctly and ready to use.

## Getting started with Poetry

Now that Poetry is installed, let's explore its core functionality. At its foundation, Poetry is a dependency and environment manager that handles project initialization, virtual environments, and package installation through a single, intuitive interface.

Poetry provides two main ways to start a project: creating a new one from scratch, or initializing an existing directory. Let's start by creating a new project:

```command
poetry new poetry-demo
```

This creates a directory named `poetry-demo`. Navigate into it:

```command
cd poetry-demo
```

Check the complete project structure using the `tree` command:

```command
tree
```
```text
[output]
poetry-demo
├── README.md
├── pyproject.toml
├── src
│   └── poetry_demo
│       └── __init__.py
└── tests
    └── __init__.py

4 directories, 4 files
```

The `pyproject.toml` file is the heart of your project. It defines metadata, dependencies, build requirements, and other configuration options. When you create a new project, Poetry generates a file that looks similar to this:

```toml
[label pyproject.toml]
[project]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = [
    {name = "Your Name",email = "your.email@example.com"}
]
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
]

[tool.poetry]
packages = [{include = "poetry_demo", from = "src"}]


[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
```

Poetry automatically creates the directory structure needed for a proper Python package:

- A `README.md` file for project documentation
- A package directory (with the same name as your project but using underscores instead of hyphens)
- A `tests` directory for your test files

This structure follows Python best practices, immediately preparing your project for development. Notice that Poetry assumes your package contains code in a directory with the same name as your project (but with underscores instead of hyphens) located in the root of your project.

In the following sections, you'll explore how to add dependencies to this project and manage your development environment.

Now, create a simple Python file to test your setup. Create a file named `app.py`:

```python
[label app.py]
import requests

response = requests.get("https://python-poetry.org")
print(f"Poetry website status code: {response.status_code}")
print("Poetry makes Python dependency management elegant!")
```

To run this file using the Poetry-managed environment, use:

```command
poetry run python app.py
```

```text
[output]

Poetry website status code: 200
Poetry makes Python dependency management elegant!`
```

This workflow means you no longer need to remember to activate environments or worry about dependency conflicts. Poetry handles everything behind the scenes, ensuring a consistent and isolated development environment.



## Managing dependencies with Poetry

In the previous section, you learned how to create a Poetry project and install basic dependencies. Now, let's explore how Poetry simplifies ongoing dependency management through its powerful commands and lockfile system.

Unlike traditional pip-based workflows, Poetry provides a complete suite of commands for adding, removing, and updating dependencies while maintaining consistent environments.

To add a new dependency to your project, use the `add` command:

```command
poetry add pandas
```

```text
[output]
Using version ^2.2.3 for pandas

Updating dependencies
Resolving dependencies... (5.0s)

Package operations: 6 installs, 0 updates, 0 removals

  - Installing six (1.17.0)
  - Installing numpy (2.2.3)
  - Installing pytz (2025.1)
  - Installing tzdata (2025.1)
  - Installing python-dateutil (2.9.0.post0)
  - Installing pandas (2.2.3)

Writing lock file
```

This command:

- Adds `pandas` to your `pyproject.toml` file with an appropriate version constraint
- Resolves all dependencies, including transitive ones
- Updates the `poetry.lock` file to ensure reproducible installations
- Installs the packages into your virtual environment

Poetry easily handles complex dependency trees, resolving potential conflicts before they become problems. If you need a specific version, use:

```command
poetry add "django>=5.1"
```

This ensures you get Django 5.1 or newer while maintaining compatibility with other packages in your project.

To remove packages you no longer need:

```command
poetry remove pandas
```

```text
[output]

Updating dependencies
Resolving dependencies... (0.1s)

Package operations: 0 installs, 0 updates, 5 removals

  - Removing numpy (2.2.3)
  - Removing pandas (2.2.3)
  - Removing python-dateutil (2.9.0.post0)
  - Removing pytz (2025.1)
  - Removing six (1.17.0)

Writing lock file
```

Poetry removes the requested package and any dependencies that are no longer required, keeping your environment clean.

When you need to update dependencies to their latest compatible versions:

```command
poetry update
```

This updates all packages to the latest versions allowed by the constraints in your `pyproject.toml`, then regenerates the lock file.

For a more targeted update of specific packages:

```command
poetry update pandas
```

One of Poetry's most powerful features is its lock file. When you clone a project with Poetry, you can guarantee identical environments across machines by simply running:

```command
poetry install
```

This uses the `poetry.lock` file to install the exact versions of all packages, eliminating "works on my machine" problems. If the lock file doesn't exist, Poetry will generate one based on the constraints in `pyproject.toml`.

To see what packages are installed in your current environment:

```command
poetry show
```

```text
[output]

asgiref  3.8.1 ASGI specs, helper code, and adapters
django   5.1.7 A high-level Python web framework that encourages rapid development and clean, pragmatic design.
sqlparse 0.5.3 A non-validating SQL parser.
```

For a dependency tree that shows relationships between packages:

```command
poetry show --tree
```


```text
[output]
django 5.1.7 A high-level Python web framework that encourages rapid development and clean, pragmatic design.
├── asgiref >=3.8.1,<4
├── sqlparse >=0.3.1
└── tzdata *
```
This comprehensive approach to dependency management ensures your Python projects remain consistent, reproducible, and free from dependency conflicts.

## Managing dependency groups in Poetry

In the previous section, we explored basic dependency management with Poetry. While adding dependencies directly to the main section is sufficient for simple projects, more complex applications benefit from organizing dependencies into groups based on their purpose.

Building on our `poetry-demo` project, let's see how Poetry's dependency groups feature helps organize project dependencies more effectively.

Let's start by adding a testing framework to a dedicated development group:

```command
poetry add --group dev pytest
```

```text
[output]

Using version ^8.3.5 for pytest

Updating dependencies
Resolving dependencies... (2.2s)

Package operations: 4 installs, 0 updates, 0 removals

  - Installing iniconfig (2.0.0)
  - Installing packaging (24.2)
  - Installing pluggy (1.5.0)
  - Installing pytest (8.3.5)

Writing lock file
```

With this command, Poetry automatically creates a development dependency group in your `pyproject.toml`:

```toml
[tool.poetry.group.dev.dependencies]
pytest = "^8.3.5"
```

This separation is powerful - it allows you to:

- Keep your production environment lean by installing only necessary dependencies
- Organize tools by their purpose
- Install specific groups only when needed

Let's expand the project by adding more development tools:

```command
poetry add --group dev black mypy
```

```text
[output]
Using version ^25.1.0 for black
Using version ^1.15.0 for mypy

Updating dependencies
Resolving dependencies... (3.4s)

Package operations: 7 installs, 0 updates, 0 removals

  - Installing click (8.1.8)
  - Installing mypy-extensions (1.0.0)
  - Installing pathspec (0.12.1)
  - Installing platformdirs (4.3.6)
  - Installing typing-extensions (4.12.2)
  - Installing black (25.1.0)
  - Installing mypy (1.15.0)

Writing lock file
```

Now your development group includes code formatting and type checking tools:

```toml
[tool.poetry.group.dev.dependencies]
pytest = "^8.3.5"
black = "^25.1.0"
mypy = "^1.15.0"
```

Beyond development tools, you can create custom groups for other purposes. For example, create a documentation group:

```command
poetry add --group docs sphinx sphinx-rtd-theme
```

Your `pyproject.toml` now contains three distinct dependency groups:

```toml
[label pyproject.toml]
...
[tool.poetry.group.dev.dependencies]
pytest = "^8.3.5"
black = "^25.1.0"
mypy = "^1.15.0"


[tool.poetry.group.docs.dependencies]
sphinx = "^8.2.3"
sphinx-rtd-theme = "^3.0.2"
```

When installing dependencies, you can choose which groups to include:

```command
# Install all dependencies including dev and docs groups
poetry install --with dev,docs

# Install only main dependencies and dev tools, but not docs
poetry install --with dev

# Install only main dependencies, no groups
poetry install --without dev,docs
```

For production deployments, you typically want only the main dependencies:

```command
poetry install --only main
```

This installs just `pendulum` and its dependencies, resulting in a lean production environment without testing, linting, or documentation tools.

When running commands with Poetry, you can use tools from specific groups without manually activating environments:

```command
# Run pytest from the dev group
poetry run pytest

# Run black from the dev group
poetry run black poetry_demo/

# Build documentation using sphinx from the docs group
poetry run sphinx-build docs _build
```


Organizing dependencies into purpose-specific groups makes your project more maintainable, with more precise separation between production dependencies and development tools. 

This approach reduces installation time, prevents unnecessary packages in production, and makes it easier for contributors to understand the purpose of each dependency.

## Final thoughts


This article explored how Poetry simplifies Python development by managing dependencies, virtual environments, and packaging in one intuitive tool. See the [official Poetry documentation](https://python-poetry.org/docs/) to learn more.

Poetry isn't the only modern tool available. You might also explore [uv](https://betterstack.com/community/guides/scaling-python/uv-explained/), another promising alternative for faster and simpler dependency management.

Thanks for reading!
