이 글은 macOS 10.15(Catalina) 환경을 기준으로 쓰여졌습니다. 윈도 및 리눅스 환경에서는 사용법이 다를 수 있습니다.

파이썬의 기본 패키지 관리자인 pip는 패키지간 의존성 및 버전 호환 관리가 힘들며, 의존성 패키지를 제외한 실제 필요 패키지의 구분이 어렵습니다.

이를 해결하기 위해 파이썬 패키지를 관리할 수 있도록 도와주는 pipenv, pipx와 같은 여러 라이브러리들이 있습니다만, 항상 약간씩 기능에 아쉬움을 느껴 지금까지는 직접 requirements.txt를 버전별로 관리하는 방법을 사용했습니다.

그러던 중 최근에 Poetry라는 관리도구를 사용해보았는데, 다른 도구들에서 불편하던 점들이 많이 개선되어 사용법을 남겨봅니다. 저는 Poetry가 자동으로 제공하는 가상환경을 사용하지 않고, PyenvPyenv-virtualenv로 직접 생성한 가상환경을 사용합니다.

Poetry 설치

스크립트를 사용한 설치

Poetry는 시스템 전역에 설치합니다. pip를 사용한 설치는 권장되지 않으며, 시스템 전역에서 사용 시 몇 가지 필요 설정이 있습니다.

19년 12월 기준, Poetry는 brew를 사용한 설치를 지원하지 않습니다.

0.9버전까지는 requirements.txt형식의 export를 지원하지 않아 베타버전을 사용해왔으나,
최근 1.0.0버전이 릴리즈 되며 일반적인 설치만으로도 쉽게 requirements.txt를 생성할 수 있게 되었습니다.

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

(Pyenv사용시) PATH설정

Pyenv를 사용하는 경우, Pyenv-virtualenv로 생성한 가상환경 중 단 하나에라도 존재하는 실행파일은 $HOME/.pyenv/shims/에서 찾게됩니다.
brew를 사용해 설치한 패키지나, 그 외에도 Pyenv로 관리되는 가상환경보다 우선하게 실행하고자 하는 명령어는 적절히 PATH의 순서를 조정해야 합니다.

저는 zsh을 쓰기 때문에 ~/.zshrc에 내용을 추가합니다. bash나 다른 셸을 사용하는 경우, 해당 셸의 설정 파일을 수정해야 합니다.

~/.zshrc

# pyenv의 PATH
export PYENV_PATH=$HOME/.pyenv
if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi
if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi

# poetry실행파일의 PATH가 pyenv의 PATH보다 우선되도록 설정합니다
export PATH=$HOME/.poetry/bin:$PATH

사용법

프로젝트의 패키지를 Poetry가 관리하도록 초기화

npm init과 비슷하게, Poetry로 해당 폴더의 패키지 관리를 시작하는 명령어를 사용합니다

# pyenv, pyenv-virtualenv를 사용하는 경우, 아래 명령어로 가상환경 생성&적용 후 실행
# pyenv virtualenv <버전> <env명>
# pyenv local <env명>

# 가상환경이 적용되지 않은 상태에서 초기화 시, Poetry가 임의의 가상환경을 생성
poetry init

이 명령어는 pyproject.toml파일을 만들어줍니다.

패키지 추가

poetry add <패키지명>

패키지 및 의존성패키지를 함께(!) 삭제

poetry remove <패키지명>

설치된 패키지 목록 확인

내가 관리하는 패키지들과, 해당 패키지들에 의존성으로 설치된 패키지들을 분리해서 볼 수 있습니다.

poetry show --no-dev --tree

# 아래와 같이 설치된 패키지와 의존성 패키지 정보를 표시
boto3 1.10.14 The AWS SDK for Python
├── botocore >=1.13.14,<1.14.0
│   ├── docutils >=0.10,<0.16
│   ├── jmespath >=0.7.1,<1.0.0
│   ├── python-dateutil >=2.1,<2.8.1
│   │   └── six >=1.5
│   └── urllib3 >=1.20,<1.26
├── jmespath >=0.7.1,<1.0.0
└── s3transfer >=0.2.0,<0.3.0
    └── botocore >=1.12.36,<2.0.0
        ├── docutils >=0.10,<0.16
        ├── jmespath >=0.7.1,<1.0.0
        ├── python-dateutil >=2.1,<2.8.1
        │   └── six >=1.5
        └── urllib3 >=1.20,<1.26
celery 4.3.0 Distributed Task Queue.
├── billiard >=3.6.0,<4.0
├── kombu >=4.4.0,<5.0
│   ├── amqp >=2.5.2,<2.6
│   │   └── vine >=1.1.3,<5.0.0a1
│   └── importlib-metadata >=0.18
│       └── zipp >=0.5
│           └── more-itertools *
├── pytz >0.0-dev
└── vine >=1.3.0
django 2.2.7 A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
├── pytz *
└── sqlparse *
django-aws-secrets-manager 0.1.2 Django secrets management tool using AWS Secrets Manager
psycopg2-binary 2.8.4 psycopg2 - Python-PostgreSQL Database Adapter
pyinquirer 1.0.3 A Python module for collection of common interactive command line user interfaces, based on Inquirer.js
├── prompt-toolkit 1.0.14
│   ├── six >=1.9.0
│   └── wcwidth *
├── pygments >=2.2.0
└── regex >=2016.11.21
supervisor 4.1.0 A system for controlling process state under UNIX

poetry.lock파일로부터 requirements.txt생성

Poetry패키지 자체는 필요하지 않은 작업(ex: Docker Image생성)시에는 현재 설치된 패키지에 대한 requirements만 필요합니다. 이 때, export명령어를 사용합니다.

poetry export -f requirements.txt > requirements.txt

# 아래와 같은 requirements.txt생성
amqp==2.5.2 \
    --hash=sha256:6e649ca13a7df3faacdc8bbb280aa9a6602d22fd9d545336077e573a1f4ff3b8 \
    --hash=sha256:77f1aef9410698d20eaeac5b73a87817365f457a507d82edf292e12cbb83b08d
billiard==3.6.1.0 \
    --hash=sha256:01afcb4e7c4fd6480940cfbd4d9edc19d7a7509d6ada533984d0d0f49901ec82 \
    --hash=sha256:b8809c74f648dfe69b973c8e660bcec00603758c9db8ba89d7719f88d5f01f26
boto3==1.10.14 \
    --hash=sha256:cb8f2531c22a4cf7847f62a9e23c2611300b6fdbcad577f67a9b56b686f78dd5 \
    --hash=sha256:aa40df7958bb274fad45ce6cc9ae1c77aac3b4cf33c34684646b42583a52d7e0
botocore==1.13.14 \
    --hash=sha256:48ad5efd98e0570df13a73e6463da2a9d9422f47a943b6ef74f950695c23dbb0 \
    --hash=sha256:d789f30a5def264b9d21a917aeadc4e5fc2b6a03a61f222befcfaf80eaba86e5
celery==4.3.0 \
    --hash=sha256:528e56767ae7e43a16cfef24ee1062491f5754368d38fcfffa861cdb9ef219be \
    --hash=sha256:4c4532aa683f170f40bd76f928b70bc06ff171a959e06e71bf35f2f9d6031ef9
django==2.2.7 \
    --hash=sha256:89c2007ca4fa5b351a51a279eccff298520783b713bf28efb89dfb81c80ea49b \
    --hash=sha256:16040e1288c6c9f68c6da2fe75ebde83c0a158f6f5d54f4c5177b0c1478c5b86

정리

제가 지금까지 사용해 본 파이썬 패키지 관리도구 중에는, Poetry가 제일 사용성이 좋았습니다. pipenv에 비해 lock파일을 생성하는 속도도 빠르며, 실 사용 및 배포환경에서 활용중입니다.

requirements를 직접 관리하게 되면, 패키지의 메이저 및 마이너 버전 업그레이드시 의존성 패키지들의 버전 관리에 일일이 대응하는데 많은 시간이 소요됩니다. 다들 적절한 패키지 관리자를 사용해서 의존성 지옥에서 벗어나봅시다!