Building Production (and Staging) Ready Python Applications

Author

Andres Monge

Published

January 23, 2024

Building production-ready Python applications requires careful planning and the right tools. In this article, we’ll explore how to use poetry and pyenv to manage dependencies, create deployable packages, and streamline the deployment process.

Why Poetry and Pyenv?

Poetry is a powerful dependency management and packaging tool for Python, while pyenv allows you to manage multiple Python versions seamlessly. Together, they ensure your project runs consistently across different environments.

Here’s how to get started:

  1. Install pyenv to manage Python versions.
  2. Install poetry to handle dependencies and packaging.

Building and Deploying with Poetry

Using poetry, you can create a .tar.gz pip package for your project and store it in a private pip repository. This simplifies installation and deployment in production environments.

For example, your Dockerfile could look like this:

FROM python:3.8  # or any other Python version
RUN pip install --index-url https://example.com/pypi/simple/ hello-app
WORKDIR /app
RUN hello-app-run

This approach ensures that your application is installed consistently, regardless of the environment.

Versioning for Development and Staging

One of the advantages of using poetry is the ability to create development or staging builds with named versions. Here’s an example of how to automate version updates in a CI/CD pipeline:

update_version.sh:

# update_version ${{ github.ref_name }}
current_version=$(poetry version -s)
date=$(date +%s)

if [ "${BRANCH_NAME}" == "development" ]; then
  new_version="${current_version}.dev${date}"
else
  new_version="${current_version}"
fi

poetry version "${new_version}"

After updating the version, don’t forget to publish the package to your private repository:

poetry build
twine upload --repository-url https://example.com/pypi/simple/

Configuring Poetry

The pyproject.toml file is the heart of your poetry configuration. Here is a quick example of what it might look like:

[tool.poetry]
name = "packvisor"
readme = "README.md"
version = "0.0.1"
packages = [{ include = "src" }]

[tool.poetry.scripts]
packvisor-run = "src.main:main"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

This configuration defines the project name, version, included packages, and entry points for your application.

Best Practices for Production-Ready Applications

  1. Use Environment Variables: Store sensitive information like API keys and database credentials in environment variables.

  2. Automate Testing: Integrate unit tests, integration tests, and linting into your CI/CD pipeline.

  3. Monitor Logs: Use a logging library like Loguru (as shown in the Logging in Python with Loguru article) to capture and analyze runtime behavior.

  4. Optimize Docker Images: Use multi-stage builds in Docker to reduce the size of your production images.

Conclusion

By leveraging poetry and pyenv, you can build, package, and deploy Python applications with confidence. Whether you’re working on a development build or deploying to production, these tools simplify the process and ensure consistency across environments.

The examples and best practices provided in this article will help you create robust, production-ready applications.