Python Best Practices for 2023

A guide to the modern Python best practices you should be using in 2023. From project management with pyproject.toml to type hints and f-strings, these are the standards for writing clean, professional Python code.

The Python ecosystem is constantly evolving. As we head into 2023, the tools and patterns that define "good" Python code have solidified around a modern, robust, and highly productive workflow. If you want to write professional Python code, these are the best practices you should be following.

1. Use pyproject.toml for Project Configuration

The days of juggling setup.py, requirements.txt, and setup.cfg are over. The modern standard for configuring a Python project is the pyproject.toml file. This single, standardized file is where you should define your project's metadata, dependencies, and the configuration for your tools (like linters and formatters).

Tools like Poetry and PDM have embraced pyproject.toml as their foundation, providing a unified way to manage dependencies, build packages, and manage your virtual environments.

2. Embrace Type Hints

Python's optional type hints are no longer just for niche use cases; they are a core part of the modern development workflow. Adding type hints to your code makes it more readable, self-documenting, and, most importantly, allows you to use static analysis tools like Mypy to catch a huge class of bugs before you even run your code.

# This is the modern standard
def get_user(user_id: int) -> dict | None:
    # ... logic

3. Use a Linter and a Formatter

Consistent code style is crucial for readability and maintainability. Two tools are essential here:

  • Black: An uncompromising code formatter that automatically reformats your code to a consistent style. This ends all arguments about code style on your team.
  • Ruff: An extremely fast Python linter written in Rust. It can check your code for hundreds of common errors and style issues in milliseconds. It has largely replaced older tools like Flake8 and isort.

Configure these tools in your pyproject.toml and run them automatically in your CI pipeline.

4. Use venv for Virtual Environments

While tools like Poetry and PDM manage virtual environments for you, it's still essential to understand the foundation: Python's built-in venv module. For any project, the first step should be to create an isolated environment.

python -m venv .venv
source .venv/bin/activate

This simple practice prevents dependency conflicts between projects and is the cornerstone of reproducible environments.

5. Use f-strings for String Formatting

Introduced in Python 3.6, f-strings are the cleanest, most readable, and fastest way to format strings. There is no longer any reason to use the older % formatting or str.format().

name = "Alice"
age = 30

# Do this:
message = f"User {name} is {age} years old."

# Not this:
message = "User %s is %d years old." % (name, age)
message = "User {} is {} years old.".format(name, age)

6. Use pathlib for Filesystem Paths

The pathlib module, introduced in Python 3.4, provides a modern, object-oriented interface for working with filesystem paths. It's more readable and less error-prone than the old os.path module.

from pathlib import Path

# The modern way
data_path = Path.cwd() / "data" / "my_file.txt"
content = data_path.read_text()

7. Use Pydantic for Data Validation

For any application that deals with data from an external source (like an API request or a config file), Pydantic is the gold standard for data validation and settings management. It uses type hints to parse, validate, and serialize data, catching errors at the boundary of your application.

8. Write Tests with pytest

pytest has won the testing framework war in Python. Its simple syntax (tests are just functions, assertions are just assert statements), powerful fixture model, and rich plugin ecosystem make it the clear choice for any new project.

Conclusion

Writing modern Python code is about more than just the language syntax. It's about embracing the rich ecosystem of tools that has grown up around it. By adopting these best practices, you can build applications that are more robust, maintainable, and easier for you and your team to work on.