Python development flow using Poetry, Git and Docker

Introduction

This article is a sister article of the previously written Python development flow using pipenv, Git and Docker. Now that Pipenv development isn't very active, I think there will be occasions when Poetry is used in projects that use Python. Therefore, I would like to reorganize the development flow using Poetry.

Overall flow

  1. Installation of development environment
  2. Project initialization
  3. Docker

Prerequisite environment

Installation of development environment

Poetry installation

In most cases, you can install it from the package manager that came with your OS.

For macOS

$ brew install poetry

Arch Linux

$ sudo pacman -S python-poetry

Ubuntu 18.04 Unfortunately, it is not registered in the standard repository, so install it from the official installer.

$ sudo apt install python3 python3-pip
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3

When the installation is complete, put your PATH in ~ / .poetry / bin. Depending on your shell, add the following settings to ~ / .zshrc and ~ / .bashrc.

~/.bashrc


export PATH=${HOME}/.poetry/bin:${PATH}

Introduction of other tools

I'll be using Git and Docker / Docker Compose in the future, so be prepared.

Initialize Python project

Now it's time to initialize your Python project with poetry.

Creating a project

First, create an appropriate directory and put it in it.

$ mkdir sample-app
$ cd sample-app

You can then initialize the project by running poetry init. It's interactive, so let's answer each one. You will be asked if you want to install the dependent packages on the way, but this time I want to install them individually, so I will skip it.

$ poetry init

This command will guide you through creating your pyproject.toml config.

Package name [sample_app]:
Version [0.1.0]:
Description []:  Sample App
Author [Aruneko <[email protected]>, n to skip]:
License []:  MIT
Compatible Python versions [^3.7]:

Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your development dependencies interactively? (yes/no) [yes] no
Generated file

[tool.poetry]
name = "sample_app"
version = "0.1.0"
description = "Sample App"
authors = ["Aruneko <[email protected]>"]
license = "MIT"

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

[tool.poetry.dev-dependencies]

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


Do you confirm generation? (yes/no) [yes]

When you exit the interactive environment, you will have pyproject.toml. This completes the project initialization.

$  ls
pyproject.toml

Poetry initial settings

Normally, a Python virtual environment created under ~ / Library / Caches / pypoetry / virtualenvs or ~ / .config / poetry will have the .venv directory directly under the project root if the following settings are added. Will be created and will manage the Python environment there. Please set as you like.

$ poetry config virtualenvs.in-project true --local

Please note that this setting is listed in poetry.toml instead of pyproject.toml.

Add package

Under Poetry environment, add packages using ʻadd` like npm. Let's develop an application that uses FastAPI as a sample.

$ poetry add fastapi uvicorn

When you install a package with Poetry, the dependent packages that can be resolved at that time and the version information of each package are written to poetry.lock.

Packages that are only used during development are also installed with the -D option, just like npm. For example, let's install the code formatter black.

$ poetry add -D black

By executing the commands so far, you can see that the packages installed so far have been added to the tool.poetry.dependencies and tool.poetry.dev-dependencies sections of pyproject.toml. ..

pyproject.toml


[tool.poetry.dependencies]
python = "^3.7"
fastapi = "^0.52.0"
uvicorn = "^0.11.3"

[tool.poetry.dev-dependencies]
black = "^19.10b0"

From now on, please install the package as needed each time.

Git initialization

Next, initialize Git to manage this project with Git. Let's use gitignore.io to create a .gitignore file first. This time, we will ask you to specify Python and virtualenv. If you need additional settings for .gitignore, edit it here.

Once you have .gitignore, initialize your Git repository, add roughly all the files and commit.

$ curl -o .gitignore https://www.gitignore.io/api/python,virtualenv
$ git init
$ git add pyproject.toml poetry.lock poetry.toml .gitignore
$ git commit -m "Initial Commit"

How to enter the virtual environment

Use the shell subcommand to enter the Python virtual environment created by Poetry. If you forget to enter the virtual environment, various problems such as not being able to see the package you should have installed will occur, so be sure to check it carefully. To exit, use the ʻexit` command.

$ poetry shell
(.venv)$ exit

Docker

Now that we have created the Poetry project, we will finally work on Docker.

Preparing .dockerignore

Files that do not need to be transferred should be entered in .dockerignore. Be sure to include it, especially if you have set the .venv file to be in the project root. In addition, it is a good idea not to transfer the __pycache__ directory.

.dockerignore


.venv/
__pycache__/

Preparing the Dockerfile

Finally, I will write a Dockerfile. This time, I will introduce the method using Multi Stage Build. It is divided into the procedure of creating requirements.txt in the first half and using it to create a Docker Image with a Python application in the second half.

The reason why you need to do that in the first place is that you need to install Poetry to read poetry.lock, but you don't need to put Poetry in the container where your application is located, so you want to separate them. Because there is an intention. Poetry has the ability to generate requirements.txt, so we'll take advantage of it.

First of all, from the explanation of the first half. To make good use of Docker's caching strategy, I install Poetry first. This will save you the trouble of installing Poetry on every build. Then it just copies pyproject.toml and poetry.lock to generate requirements.txt.

Next is the explanation of the latter half. Copy the resulting requirements.txt from the first half and then use the pip command to install all those packages. If these files are unchanged, the cache will be used to automatically build the next layer, so you can prevent the behavior of downloading dependent packages every time you build. .. This is a recommended configuration because it can save overwhelming build time. After the installation is complete, transfer various Python scripts and write the commands you want to run, and you're done.

FROM python:3.8-slim as builder

WORKDIR /usr/src/app

RUN pip install poetry

COPY pyproject.toml poetry.lock ./

RUN poetry export -f requirements.txt > requirements.txt


FROM python:3.8-slim

ENV PYTHONUNBUFFERED=1

WORKDIR /usr/src/app

COPY --from=builder /usr/src/app/requirements.txt .

RUN pip install -r requirements.txt

COPY . .

EXPOSE 8000
CMD [ "uvicorn", "main:app", "--host", "0.0.0.0" ]

It's also a good idea to set up Docker Compose as well. It may be a good idea to mount the local file for development and then set the auto reload settings.

docker-compose.yml


version: '3'

services:
  app:
    build: .
    volumes:
      - ./:/usr/src/app
    ports:
      - "8000:8000"
    command: ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0"]

FAQ

How to update the package

You can use poetry update. However, it will not be updated beyond the version described in pyproject.toml, so please be careful when upgrading major versions.

How to remove a package

You can remove it with poetry remove PACKAGE_NAME.

If you participate in development from the middle

You can install the entire development dependency package with poetry install.

in conclusion

So far, we have explained the development flow of a Python project using Poetry. In Poetry as well as Pipenv, I think that by utilizing poetry.lock, it is possible to eliminate the version difference between developers and provide a stable development environment. It also follows the format agreed upon by PEP, so it feels like it's not bad for the future.

On the other hand, I get the impression that it is a project management tool for ** Python package developers ** rather than Python applications, such as lacking the script function that runs the one-liner that was possible with Pipenv. I use it quite a bit to run Lint and other tests, but this feature.

So both Poetry and Pipenv have their advantages and disadvantages. At this point, I think it's safe to choose the one that suits your project. I hope you all have a good Python life.

Recommended Posts

Python development flow using Poetry, Git and Docker
Develop and deploy Python APIs using Kubernetes and Docker
Manage Python runtime packages and development environment packages with Poetry
Authentication using tweepy-User authentication and application authentication (Python)
Clustering and visualization using Python and CytoScape
Python3 socket module and socket communication flow
Application development with Docker + Python + Flask
Build and try an OpenCV & Python environment in minutes using Docker
Create a simple Python development environment with VS Code and Docker
Notes using cChardet and python3-chardet in Python 3.3.1.
From Python to using MeCab (and CaboCha)
Python development environment for macOS using venv 2016
Using venv in Windows + Docker environment [Python]
Behind the flyer: Using Docker with Python
Using Python and MeCab with Azure Databricks
[FX] Hit oanda-API in Python using Docker
6 Python libraries for faster development and debugging
Build a development environment using Jupyter and Flask with Python in Docker (supports both VS Code / code-server)
Development and deployment of REST API in Python using Falcon Web Framework
[Python] PyPI package publishing procedure using poetry
I'm using tox and Python 3.3 with Travis-CI
Windows + gVim + Poetry python development environment construction
Three things I was addicted to when using Python and MySQL with Docker
Head orientation estimation using Python and OpenCV + dlib
I tried web scraping using python and selenium
Notes on installing Python3 and using pip on Windows7
I tried object detection using Python and OpenCV
Python development on Ubuntu on AWS EC2 (using JupyterLab)
[Python] Build a Django development environment with Docker
Get git branch name and tag name with python
Create a web map using Python and GDAL
python development environment -use of pyenv and virtualenv-
[Python3] Automatic sentence generation using janome and markovify
Try using tensorflow ① Build python environment and introduce tensorflow
Create a Mac app using py2app and Python3! !!
From easy git installation to docker startup python
Continuation of multi-platform development with Electron and Python
Build PyPy and Python execution environment with Docker
Try using ChatWork API and Qiita API in Python
Get a quick Python development environment with Poetry
Start using Python
python at docker
Scraping using Python
Initial settings for using Python3.8 and pip on CentOS8
Searching for pixiv tags and saving illustrations using Python
Extendable skeletons for Vim using Python, Click and Jinja2
Try creating a compressed file using Python and zlib
Directory structure for test-driven development using pytest in python
Building a Docker working environment for R and Python
[Python] Easy Google Translate app using Eel and Googletrans
Send and receive Gmail via the Gmail API using Python
Implementing a generator using Python> link> yield and next ()> yield
Install and develop Git, VSCode, Docker on Chrome OS
Read and write files with Slackbot ~ Bot development with Python ~
Python development environment construction 2020 [From Python installation to poetry introduction]
Get and automate ASP Datepicker control using Python and Selenium
Read and write NFC tags in python using PaSoRi
Build a Python development environment using pyenv on MacOS
Speech transcription procedure using Python and Google Cloud Speech API
python package dependencies and virtual environment management tool Poetry
Get files from Linux using paramiko and scp [Python]