(python) poetry 입문과 사용법 (1)

종속성 관리의 필요성 / poetry의 등장 / 주요 명령어 정리 / lock 파일

  ·   4 min read

파이썬에서 종속성 라이브러리를 관리하는 패키지 매니저인 poetry에 대해 알아보도록 하자.

종속성 관리의 필요성

python은 혼자 코딩하기 참 편하지만, 다수와 같이 작업하는 순간 고려해야할 점들이 굉장히 많아진다. 그 중 하나는 패키지 종속성으로 인한 문제인데, 시스템에 설치된 파이썬 라이브러리와 호환되지 않거나, 설치해야할 라이브러리들 간의 버전이 충돌되는 문제가 발생할 수 있다.

이에 두가지 해결책이 제안된다.

  1. 가상환경 프로젝트마다 독립적인 python 환경을 갖도록 한다. global package는 지양하고, 프로젝트마다 고유한 virtual environment를 만들어 사용하도록 한다.

    python3에는 기본 기능으로 내장되어 있어, python -m venv {가상환경 이름}의 꼴로 현재 디렉토리에 가상환경에 대한 폴더가 생기고, source 등의 명령어를 통해 가상환경을 활성화할 수 있다. 참고

    가상환경이 활성화된 이후에는 python, pip 명령어는 기본적으로 가상환경을 바라보게 될 것이다.

  2. 종속성 파일 라이브러리간 의존성과 그로 인한 충돌을 관리하기 위해 버전을 관리할 필요가 있다. 보통 requirements.txt 파일에 필요한 패키지의 버전을 명시하도록 하고, 사용자는 pip install -r requirements.txt로 이를 설치하는 것이 관례이다.

간단한 프로젝트의 경우, 가상환경을 활성화하고 종속성 파일로부터 라이브러리를 설치하여 진행하곤 한다.

poetry의 등장

물론, venv 모듈과 pip + requirements.txt 의 조합으로 naive하게 문제를 해결할 수 있지만, requirements.txt는 다음의 한계점이 존재한다.

  1. 라이브러리 간의 충돌 라이브러리의 의존성 패키지끼리 충돌할 경우, 이를 추적하고 requirements.txt를 일일이 수정해야 한다.

  2. requirements.txt를 수정하는 것의 문제 javascript의 패키지 관리자인 yarn, npm은 별도의 lock file을 두어 버전의 필수 조건 뿐 아니라 실제 설치된 버전을 명시한다. 또한 해당 lock file를 개발자가 임의로 수정하지 못하도록 하여, lock file을 통해 동일한 라이브러리 환경을 갖게 된다.

    requirements.txt의 경우, pip freeze > requirements.txt와 같이 freeze 명령어를 통해 현재 환경에 설치된 정보를 기록할 수 있지만, 위의 충돌을 해결하는 과정에서 개발자가 직접 수정해야한다..

앞서 언급했던 문제들을 해결하기 위해 poetry 도입을 검토해볼 수 있다. 의존성 관리를 포함하여 가상환경, 프로젝트 관리와 패키지 배포 등 파이썬 프로젝트를 진행하는데 있어 많은(어쩌면 굳이 고민하고 싶지 않은) 기능들을 지원한다.

poetry 주요 명령어 정리

poetry는 시스템에 글로벌하게 설치하는 것이 좋다. 참고

초기 설정 - poetry new / poetry init

poetry를 설치한 이후, poetry init으로 interactive하게 기존 디렉토리의 package manager를 poetry로 설정할 수 있다. 기존 프로젝트가 이미 있다면 poetry init, 아니면 poetry new 명령어로 프로젝트 시작을 수행할 수도 있다.

> poetry new hello-project
Created package hello_project in hello-project

> ls hello-project
README.md  hello_project  pyproject.toml  tests

new 명령어로 생성한 경우에는 위와 같이 프로젝트 폴더와 README, 그리고 테스트 폴더까지 생성됨을 확인할 수 있다. 모든 입력을 완료하면 아래와 같이 pyproject.toml파일이 생긴다.

[tool.poetry]
name = "hello-project"
version = "0.1.0"
description = ""
authors = ["choieastsea <email>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.9"
  
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

참고: toml 파일은 [ ] 안에 섹션 이름, 그리고 key = value의 꼴로 데이터를 표현하는 방법. 공식 문서 pyproject.toml 에는 다음과 같은 프로젝트의 정보를 담고 있다. (pyproject.toml은 poetry에서만 있는 사양이 아닌 파이썬 프로젝트의 정보를 담는 공식 스펙이라고 생각하자)

  • 프로젝트 기본 정보
  • 사용하는 라이브러리
  • 빌드 정보

가상환경 활성화 - poetry shell

poetry 가상환경은 프로젝트 루트 디렉토리(pyproject.toml이 있는 곳)에서 poetry shell 명령어를 통해 활성화 할 수 있다.

하지만 기본적으로 poetry 설치 위치(사용자 시스템 어딘가)에 가상환경이 세팅되는데 이는 독립적이긴 하지만, 라이브러리의 소스 코드를 추적하고 싶을 때 곤란할 수 있다.

이때, poetry config virtualenvs.in-project true 명령어를 통하여 이후 생성할 가상환경을 현재 디렉토리에 생기게 할 수 있다. 혹은 poetry.toml이라는 파일에 in-project 키를 true로 정해줘도 된다. (pyproject.toml은 해당 project에 대한 정보를 담고, poetry.toml은 해당 poetry에 대한 정보를 담으므로 구분하자)

poetry shell로 가상환경을 생성하고, (이미 생성되었다면) 활성화할 수 있다.

라이브러리 추가 - poetry add / poetry remove

이제, 라이브러리를 추가해보자! toml 파일에 직접 작성할 수도 있지만, 보통 poetry add로 자동으로 파일에 추가되도록 한다.

> poetry add aiohttp
Using version ^3.9.3 for aiohttp

Updating dependencies
Resolving dependencies... (0.3s)

Package operations: 8 installs, 0 updates, 0 removals

  • Installing frozenlist (1.4.1)
  • Installing idna (3.6)
  • Installing multidict (6.0.5)
  • Installing aiosignal (1.3.1)
  • Installing async-timeout (4.0.3)
  • Installing attrs (23.2.0)
  • Installing yarl (1.9.4)
  • Installing aiohttp (3.9.3)

버전의 경우 명시할 수 있는데, 여기를 참고하여 작성하면 좋다. 항상 특정 버전을 사용하도록 하는 것은 피곤한 일이다…

위와 같이 의존하고 있는 특정 버전의 라이브러리를 먼저 설치한 이후에 요청한 라이브러리를 설치하는 것을 확인할 수 있다.

poetry add 명령어 수행시, pyproject.toml에는 요청한 라이브러리의 버전 제약이 명시되고, poetry.lock 파일에는 하위 의존성을 포함한 설치된 라이브러리 버전이 명시된다.

poetry.lock

라이브러리를 설치하면 poetry.lock 파일이 생기는데, 해당 파일은 사용자가 임의로 라이브러리의 종속관계를 정의하지 못하도록 hash값을 붙여 제공된다.

파일 시작부터 # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.라고 하는걸 보면, 건들라고 만든 파일이 아니다!!

poetry 명령어를 통해 패키지를 삭제하거나 버전을 변경하면 해당 사항이 lock 파일에도 반영되므로 참고하자. pyproject.toml은 (해당 라이브러리를 사용하기 위한)프로젝트 제약, poetry.lock은 설치 제약이라고 이해하면 좋을 것이다. lock파일을 통해 프로젝트의 의존성 이외에 하위 의존성을 확인할 수 있다. 예컨대 위에서 aiohttp 모듈을 명시하여 toml에 적히지만, 이를 포함한 하위의 frozenlist, idna 등은 lock파일에 적어주는 것이다.

이렇게 2개(프로젝트 정보/lock)의 파일로 관리하는 것은, 라이브러리가 매우 복잡한 javascript 진영에서 유명하다.

poetry.lock 파일도 git으로 관리하자.

협업시에는 poetry.lock을 일치시켜 같은 종속성 환경을 유지시키는 것이 좋다.

의존하고 있는 라이브러리를 가상환경에서 제거하고 싶을 때에는 poetry remove {library}를 실행하자.

라이브러리 실행 - poetry run

가상환경에서 설치한 라이브러리를 cli 환경에서 실행하고 싶다면 poetry run {library}와 같이 실행할 수 있다. python 실행 또한 poetry run python main.py와 같이 실행할 수 있다.

다음에는 추가적인 설정과 함께, 다른 사람이 만든 project를 가져와 세팅할 때 어떻게 설정할지도 알아보자!

화이팅!

참고

poetry 공식 문서