본문 바로가기

기록

Poetry로 파이썬 의존성 관리하기

Poetry?

파이썬에서 사용하는 의존성 관리자는 몇 가지가 있습니다. 파이썬의 공식 의존성 관리자인 pip, 그리고 pipvirtualenv를 같이 사용할 수 있는 Pipenv가 있고, 이번에 소개할 Poetry가 있습니다. 현재 회사에서 pipvenv를 사용하여 프로젝트를 진행하고 있는데, 생각보다 번거롭기도 하고, 의존성 관리가기가 영 쉽지 않아서 PipenvPoetry를 고려하고 있습니다. 여기서는 Poetry를 직접 설치하고 간단하게 써보도록 하겠습니다.

pip가 불편한 이유

저는 회사에서 pip를 쓰면서 불편했던 경험이 있습니다. 처음부터 관리를 잘 한 프로젝트의 경우엔 큰 문제가 없었지만, 오래된 프로젝트나 여러 번 패키지 업데이트를 거치면서 여러 사람의 손을 탄 경우가 문제였습니다. requirements.txt 관리가 제대로 되지 않아 의존 패키지들의 버전 충돌이 생겨서 제대로 패키지를 설치할 수 없는 경우가 상당히 많았습니다. 이를 해결하기 위해서 일부 패키지 버전을 수정해야 하기도 했고, 정확히 어떤 패키지로 인해 해당 패키지가 필요한지 알 수 없는 경우가 많았죠. requirements.txt를 관리가기가 쉽지 않기 때문에 어떤 사람은 일일히 설치한 패키지들을 일일히 적기도 하고, 또 어떤 사람은 pip freeze > requirements.txt를 통해 해당 환경에 설치된 모든 패키지 목록을 그대로 입력해버렸기 때문에 생기는 문제였습니다. 어쨌든 requirements.txt 파일을 관리하기가 번거로워 생기는 문제였죠.

또 다른 문제는 venv와 같은 가상환경을 굳이 따로 설정해주어야 하는 문제점이 있었습니다. 프로젝트를 만들거나 로컬에 복제할 때 항상 아래의 명령어를 입력한 후 프로젝트를 작업할 수 있습니다.

$ pyenv local 3.9.9
$ python -m venv venv
$ pip intall -r requirements.txt

프로젝트가 단 하나라면 큰 문제는 없지만, 여러 가지 프로젝트를 작업하게 된다면 귀찮기도 하고 생각보다 깜빡하는 경우도 많아서 불편합니다. 하지만 Poetry는 이 불편한 점들을 꽤나 편하게 해결해줍니다. 의존성 정보를 모두 명령어로 기록하고 관리할 수 있고, 가상환경까지 자동으로 만들어 주기 때문에 프로젝트를 작업하는 데 있어 큰 불편함이 없었습니다.

Poetry 설치하기

먼저 macOS에서는 Homebrew를 통해 간편하게 설치가 가능합니다.

brew install poetry

Linux, BashOnWindows에서는 아래의 명령어를 통해 설치를 하면 됩니다.

$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -

설치한 이후 쉘을 다시 시작하거나 source $HOME/.poetry/env을 입력한 후, 아래 명령어를 통해 설치가 잘 되었는지 확인할 수 있습니다.

$ poetry --version
Poetry version 1.1.12

추후에 Poetry를 업데이트를 해야할 경우 poetry self update 명령어를 통해 업데이트 할 수 있습니다.

다른 설치 방법은 아래 링크를 참고하시면 됩니다.

tab 자동완성 설정하기

zsh, fish, bash를 사용할 경우 tab을 사용한 자동완성을 설정할 수 있습니다.

# Bash
$ poetry completions bash > /etc/bash_completion.d/poetry.bash-completion

# Bash (Homebrew)
$ poetry completions bash > $(brew --prefix)/etc/bash_completion.d/poetry.bash-completion

# Fish
$ poetry completions fish > ~/.config/fish/completions/poetry.fish

# Fish (Homebrew)
$ poetry completions fish > (brew --prefix)/share/fish/vendor_completions.d/poetry.fish

# Zsh
$ poetry completions zsh > ~/.zfunc/_poetry

# Oh-My-Zsh
$ mkdir $ZSH_CUSTOM/plugins/poetry
$ poetry completions zsh > $ZSH_CUSTOM/plugins/poetry/_poetry

# prezto
$ poetry completions zsh > ~/.zprezto/modules/completion/external/src/_poetry

zsh를 사용할 경우 ~/.zshrc 파일의 compinit 이전에 아래 라인을 추가해줍니다.

fpath+=~/.zfunc

oh-my-zsh를 사용할 경우 ~/.zshrc에 아래처럼 추가해줍니다.

plugins = (
    poetry
    # ...
)

이후 Poetry 명령어를 입력하고 tab를 입력하면 사용할 수 있는 명령을 확인할 수 있습니다.

기본 사용법

신규 프로젝트 설정

poetry-demo라는 신규 프로젝트를 만들어 봅시다.

$ poetry new poetry-demo

Poetry를 통해 만들어진 신규 프로젝트의 경우 아래와 같은 파일 구조를 가지고 있습니다.

poetry-demo
├── pyproject.toml
├── README.rst
├── poetry_demo
│   └── __init__.py
└── tests
    ├── __init__.py
    └── test_poetry_demo.py

이 중 pyproject.toml 파일은 프로젝트에 대한 중요한 정보들을 가지고 있습니다. 간단한 프로젝트에 대한 정보, 사용하는 Python 버전, 사용하는 의존성에 대한 정보를 모두 가지고 있습니다.

[tool.poetry]
name = "poetry-demo"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]

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

[tool.poetry.dev-dependencies]
pytest = "^5.2"

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

기존 프로젝트 설정

만약 Poetry를 기존 프로젝트에 사용하고 싶다면 아래 커맨드를 통해 설정할 수 있습니다

$ cd pre-existing-project
$ poetry init

의존성 관리

의존성을 관리하는 방법엔 크게 두 가지 방법이 있습니다. 하나는 pyproject.toml 파일에 직접 추가하는 것이고, 나머지 하나는 poetry add 명령어를 사용하는 것입니다. 직접 pyproject.toml 파일에 패키지 정보를 추가할 때에는 tool.poetry.dependencies에 의존성 정보를 입력하고

[tool.poetry.dependencies]
fastapi = "^0.70.1"

pyproject.toml 파일을 수정하는 대신 아래 명령어를 통해서 의존성 정보를 기록하고 동시에 설치도 진행할 수 있습니다.

# 최신 버전 설치
$ poetry add fastapi

# 설치하고 싶은 버전을 지정해서 설치
$ poetry add fastapi==0.70.1

해당 명령어를 사용하여 의존성을 관리하면, 수동으로 의존성을 관리할 필요 없이 자동으로 직접 설치한 의존성만 기록이 되므로 편하기도 하지만 실수를 할 일이 줄어듭니다.

Poetry는 기본적으로 의존성을 PyPI에서 찾습니다. 하지만 상황에 따라 다른 레포지토리를 사용할 일이 있는데, 이 때에는 tool.poetry.repositories 부분을 아래와 같이 설정해주셔야 합니다.

[[tool.poetry.repositories]]
name = "{레포지토리 이름}"
url = "{레포지토리 URL}"

가상환경 사용하기

기본적으로 Poetry{cache-dir}/virtualenvs 디렉토리에 가상환경을 설정합니다. cache-dirpoetry config 명령어를 통해 임의로 설정할 수 있으며, virtualenvs.in-project 설정 변경을 통해 가상환경이 프로젝트 내에 위치하도록 할 수도 있습니다.

# 가상환경이 프로젝트 내부에 위치하도록 수정
$ poetry config virtualenvs.in-project true

그러면 이제 가상환경을 실행할 수 있는 몇 가지 방법에 대해 알아봅시다.

poetry run

간단하게 가상환경에서 스크립트를 실행하려면 poetry run python script.py 명령어를 통해 실행할 수 있습니다. pytest와 같은 명령어의 경우엔 poetry run pytest와 같이 사용할 수 있습니다.

가상환경 활성화하기

새 쉘과 함께 가상환경을 활성화하는 방법은 poetry shell 명령어를 이용하는 것입니다. 활성화된 가상환경을 비활성화하면서 생성된 쉘을 종료하려면 exit 명령어를 사용하고, 새 쉘 종료 없이 활성화된 가상환경만 종료하려면 deactivate 명령어를 사용하면 됩니다.

왜 새 쉘인가요?

자식 프로세스는 부모로부터 환경을 상속받지만 이를 공유하지는 않습니다. 따라서 자식 프로세스가 수정한 내용은 자식 프로세스가 종료되면 유지되지 않습니다. 자식 프로세스로 실행되는 파이썬 애플리케이션(Poetry)은 Poetry 명령어가 실행이 완료한 후에도 활성화되어 있는 가상환경이 활성 상태를 유지하도록 호출된 쉘의 환경을 수정할 수 없습니다.

따라서, Poetry는 가상환경 내에서 후속 명령을 실행되도록 가상환경을 활성화한 하위 쉘을 생성합니다.

새 쉘을 생성하지 않으려면 source {path_to_venv}/bin/activate 명령어를 사용하여 수동으로 가상환경을 활성화할 수 있습니다. 가상환경의 경로는 poetry env info --path 명령어를 입력해서 확인할 수 있습니다. 또한 source $(poetry env info --path)/bin/activate 명령어로 한 줄로 실행할 수 있으며, deactivate 명령어를 통해 가상환경을 비활성화할 수 있습니다.

버전 제약조건

위 예시에서 fastapi 패키지의 정보가 ^0.70.1 버전으로 기록되어 있습니다. 이는 0.70.1 버전 이상, 1.0.0 버전 이하의 버전을 의미합니다(>=0.70.1 <1.0.0). 의존성 버전에 대해 자세히 알고 싶으시다면 아래 링크를 참조해주세요.

의존성 설치

기본적으로 pyproject.toml에 기록되어 있는 의존성을 설치하기 위해서는 아래 명령어를 실행해야 합니다.

$ poetry install

poetry.lock이 없을 때

poetry install 명령어를 입력한 적이 없고, poetry.lock 파일이 없는 경우에, Poetrypyproject.toml에 기록된 의존성들을 최신 버전의 다운로드를 통해 설치합니다. 설치가 끝났을 때는 다운로드 받은 패키지들의 버전 정보를 이용하여 poetry.lock 파일을 생성합니다. 해당 프로젝트를 사용하는 모든 사용자들이 같은 버전의 의존성을 사용할 수 있도록 poetry.lock을 반드시 커밋해야 합니다.

poetry.lock이 있을 때

poetry.lock 있으나 없으나 pyproject.toml을 사용하여 의존성 정보를 확인하여 설치하지만, poetry.lock 파일이 존재할 경우 해당 파일에 나열된 정확한 버전을 설치해서 해당 프로젝트를 작업하는 모든 사용자의 의존성 버전이 일치하도록 합니다. 결과적으로 pyproject.toml에 나열되어 있는 모든 의존성을 해결하지만, 모든 의존성이 최신 버전이 아닐 수도 있습니다. 이는 의도치 않은 의존성 버전의 변경으로 인해 프로젝트가 망가지지 않도록 하기 위한 것입니다.

Poetry 사용 후기

Poetry를 사용하면서 가장 편리했던 건, NodeJSnpm이나 yarn처럼 명령어를 통해 의존성에 대한 관리를 할 수 있다는 점이었습니다. 또한 poetry.lock 파일을 통해 직접적으로 연관되어 있지 않은 의존성의 버전도 여러 명이 사용하는 프로젝트의 경우에도 정확한 버전의 의존성 사용할 수 있는 점도 상당히 편리했습니다. 이전에 venvpip를 같이 사용할 때엔 가상환경 만들고, 패키지를 설치하는 과정이 따로따로 이루어졌기 때문에 실수로 글로벌 환경에 설치하는 경우도 있었는데, poetry install 명령어 한 번이면 해결되는 점도 무척 편했습니다. 아직 깊게 사용해보지는 못했지만, Poetry의 문서를 보니 좀 더 다양한 것들을 할 수 있을 것 같습니다. 좀 더 다양한 기능들을 사용해볼 수 있도록 사용해봐야겠습니다.

Poetry에 대해 더 깊은 정보는 역시 공식 홈페이지를 참고하시는 게 좋습니다. 저 또한 사용하면서 괜찮거나 좋은 기능이 있다면 블로그에 열심히 소개하도록 하겠습니다. 글 봐주셔서 감사합니다.