Skip to content

Information on how to structure a python project, based on the Hexagonal Architecture pattern

Notifications You must be signed in to change notification settings

devsjc/python-project-structure

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MODERN PYTHON MICROSERVICE

Template for creating src-layout PEP628 compliant hexagonal python microservice.


Repo containing a template for creating a modern Python microservice. The template is designed to contain the important parts of a Hexagonal python microservice, with a minimal dockerfile and a CI workflow that builds and tests the service. It uses modern python standards, such as pyproject.toml and src-layout, and is designed to be easily extended. The contents of this README are an example of what you might expect to find in a well-documented service.

Running the service

Depending on the source and sink you choose to read and write data from, environment variables will need to be set. The program will inform you of missing env vars, but you can also check the config for the given module.

CLI

Whether running via Docker or the Python package, available commands can be found with the command help or the --help flag. For example:

$ package-name --help
# or
$ docker run ghcr.io/user/package-name:latest --help

Ubiquitous Language

The following terms are used throughout the codebase and documentation. They are defined here to avoid ambiguity.

  • Ubiquitous Language - The language describing terms relevant to the bounded context of the service. These are high-level business descriptions of the function of the application, not code-specific terms.

Repository structure

Produced using exa:

$ exa --tree --git-ignore -F -I "*init*|test*.*"
./
├── Containerfile # Dockerfile for building the image
├── pyproject.toml # The build configuration for the service
├── README.md
└── src/
   ├── package_name/ # The python package
   │  ├── cmd/
   │  │  └── main.py # The entrypoint for the service
   │  └── internal/ # Packages internal to the service. Akin to 'lib' folder
   │     ├── config/
   │     │  └── config.py # Configuration for the service
   │     ├── models.py
   │     ├── outputs/ # Holds subpackages for each data sink
   │     └── service/ # Contains the business logic and use-cases of the application

package-name is structured following principles from the hexagonal architecture pattern. In brief, this means a clear separation between the application's business logic - it's Core - and the Actors that are external to it. In this package, the core of the service is in internal/service/ and the actors are in internal/inputs/ and internal/outputs/. The service logic has no knowledge of the external actors, instead defining interfaces that the actors must implement. These are found in internal/models.py. The actors are then responsible for implementing these interfaces, and are dependency-injected in at runtime. This allows the service to be easily tested and extended. See further reading for more information.

Local development

Clone the repository and create and activate a new python virtualenv for it. cd to the repository root.

Install the Python dependencies as shown in the section below.

Python requirements

Install the required python dependencies (including dev dependencies) and make it editable with

$ pip install -e .[dev] 

This looks for requirements specified in the pyproject.toml file.

Where is the requirements.txt file?

There is no requirements.txt file. Instead, the project uses setuptool's pyproject.toml integration to specify dependencies. This is a new feature of setuptools and pip, and is the recommended way to specify dependencies. See the setuptools guide and the PEP621 specification for more information, as well as Further Reading.

Running tests

Ensure you have installed the Python requirements.

Run the unit tests with

$ python -m unittest discover -s src/package_name -p "test_*.py"

and the integration tests with

$ python -m unittest discover -s test_integration -p "test_*.py"

See further reading for more information on the src directory structure.

Linting and autoformatting

This project uses Ruff for linting and autoformatting. It can be run whilst developing via

$ ruff check --watch --fix src

Further reading

On packaging a python project using setuptools and pyproject.toml:

On hexagonal architecture:

On the directory structure:


About

Information on how to structure a python project, based on the Hexagonal Architecture pattern

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published