[ 글의 목적: python 프로젝트의 의존성 관리와 패키징을 위한 poetry 세팅부터 활용까지 기록 ]
python 진영에서는 "가상환경" 그리고 "의존성" 그리고 "빌드" 그리고 ... 등 과 같이 특수 목적에 따라 다른 라이브러리, 써드파티를 사용해왔다. 게다가 make file도 말이다. (물론 개인의 선택 및 취향이다.) 이제 poetry 를 활용해
pyproject.toml
을 중심으로 프로젝트 관리를 하나의 tool로 해결해보자!
python은 pip
, pipenv
, setuptools
, distutils
, (가상 환경만으로) venv
등과 같은 여러 패키지 및 의존성 관리 도구를 가지고 있다.
하지만 해당 도구들은 "각각 특별한 사용 사례를 목표로 설계" 되었기 때문에, 파이썬 커뮤니티는 "통합된, 일관된, 및 사용자 친화적인 도구" 에 대한 니즈가 계속 있었고 이러한 필요성이 "poetry"의 탄생 배경이 되었다.
개발하면서 패키지 추가하고 서로 의존성 관리도 해야 하고, 자체 가상환경도 구성해야 하고, 만약 Pypi 라이브러리 등록하려면 setup 이나 기타 등등 신경쓸게 많다. (물론 지금도 그렇지만) 그래서 setuptools
나 distutils
등을 활용하지만 기본적으로 필요한 설정 파일 (setup.py, setup.cfg, MANIFEST.in) 이 너무 많다.
게다가 라이브러리간 의존성 해결과 패키지 업데이트는 pip과 pipenv에서 아직 완벽하게 처리되지 않았다. 이러한 답답함과 통일성에 대한 니즈의 교집합으로 최근에 poetry
가 굉장히 각광 받았다. 23년도 pycon 에서도 poetry
에 대한 내용이 유독 많은 이유가 지금은 정말 사용할만 해졌기도 해서다!
내 프로젝트에 필요한 A, B가 있고, B는 A의 2.0버전 이상 (>= A 2.0) 을 요구한다고 하자. pip으로 설치하게 되면 내가 A을 1.0버전으로 설치한다고 해도 아무런 문제가 발생하지 않는다. 이 문제는 실행해 보고 에러메시지를 마주한 뒤에 깨닫는 경우가 대부분이다.
하지만 poetry는 "버전 관련 정보를 확인하고" 특정 버전 이상이 아닐 경우에 아예 설치가 되지 않는다.
pip
은 lock
파일이 없고, 직접 requirements.txt
를 작성해야 한다. 게다가 사실 이 리콰파일도 그냥 출력 >>
으로 만든다. 반면 poetry
는 lock
파일과 pyproject.toml
을 자동으로 생성 및 업데이트해준다. 더 정확하게는 pyproject.toml
중심으로 모든 라이브러리 및 프로젝트 관리가 시작된다.
가상환경을 구성하지 않으면 pip
은 전역에 패키지를 설치하기 때문에, 해당 설치툴로는 다른 환경에서의 버전 관리가 불가하다.
그래서 기본적으로 존재하는 venv
또는 미니콘다나 virtualenv
같은 툴이 부가적으로 필요하게 된다. 사용자마다 결국 다 다른 가상환경이며 특수 목적으로 만들어진 가상환경 겸 라이브러리도 있다. 반면 poetry는 가상환경 여부를 확인하고 기존 환경, 혹은 새로 만들어 설치하는 등 자동으로 관리해준다.
python 진영에서는 "가상환경" 그리고 "의존성" 그리고 "빌드" 그리고 ... 등 과 같이 특수 목적에 따라 다른 라이브러리, 써드파티를 사용해왔다. 게다가 make file도 말이다. (물론 개인의 선택 및 취향이다.)
이제 그러한 모든 부분을 poetry
를 중심으로 세팅할 수 있다!
기본적으로 Poetry는 프로젝트의 Python "버전을 명시" 하기때문에 다양한 버전의 Python에 대해 패키지를 생성하거나 테스트할 수 있도록 지원한다. 그리고 Poetry 1.2.0부터 플러그인 시스템을 지원하게 되어, 커뮤니티에서 다양한 확장 기능을 개발하고 공유할 수 있게 되었다.
curl -sSL https://install.python-poetry.org | python3 -
로 설치하기install.python-poetry.org 를 들어가보면 알겠지만 python으로 작성된 code 파일 덩어리다. 해당 파일을 꼭 python 3.7 버전 이상 에서 설치해야 한다.
설치중 SSL: CERTIFICATE_VERIFY_FAILED
이슈 발생시 pip install --upgrade certifi
로 certifi의 버전업을 해줘야한다.
poetry --version
를 입력하면 command not found: poetry
가 응답할 것이다. poetry 설치과정에서는 우리의 command shell에 PATH를 자동으로 세팅해주는 과정이 없다. 그래서 본인이 사용하는 command shell에 알아서 PATH를 추가해야 한다.
PATH 설정을 왜 해야할까? 에 대한 의문이 생기면 해당 글을 추천한다. (클릭)
mac기준 zshrc가 standard 이기 때문에 해당 설정파일에 다음 cli로 추가해 준다. echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
그리고 source ~/.zshrc
로 적용된 PATH를 지금 shell에도 적용시켜 준다.
poetry --version
로 설치를 확인한다! poetry self update
를 통해서 업데이트를 진행할 수 있다. mkdir my_project
cd my_project
poetry init
위 과정에서 Package to add ...
구간에서 미리 사용 및 활용할 패키지를 명시하면 가상환경 생성을 하고 활성화할때 자동으로 설치 및 세팅해준다.
init
대신 poetry new <project name>
명령어를 통해 디렉토리 생성까지 한 번에 할 수 있다. 이 경우 아래와 같이 디렉토리가 자동으로 구성된다.
my_project
├── pyproject.toml
├── README.md
├── my_project
│ └── __init__.py
└── tests
└── __init__.py
poetry는 의존성을 설치할 때 자동으로 가상환경을 생성한다. poetry install
을 통해서 pyproject.toml
에 명시된 의존성을 설치하며, 가상환경을 만든다. 만약 아직 의존성이 정의되지 않았다면, 이 명령은 그냥 가상환경을 만든다.
그리고 poetry shell
를 통해서 가상환경을 activation 할수 있다.
poetry add <package_name>
를 통해 패키지를 추가 및 install 할수 있다.pyproject.toml
의 tool.poetry.dependencies
에 추가가 된다.python - flake8, Black 도입, pre-commit & clean code-style 실천하기
와 같이 python은 프로젝트 init 부터 린팅을 세팅하고 출발하면 좋다.
poetry add --group dev black flake8
을 통해 패키지를 추가하고 pyproject.toml
파일에 아래 설정값을 추가하자
# 아래 섹션은 black의 설정
[tool.black]
line-length = 88
target-version = ['py38']
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''
# 아래 섹션은 flake8의 설정
[tool.flake8]
ignore = "E203, E501, W503"
max-line-length = 88
exclude = ".git,__pycache__,docs/,old/,build/,dist/"
poetry run black .
& poetry run flake8
과 같이 실행해서 해당 린팅을 세팅할 수 있다. 이건 완전 취향인데 위 설정 그대로 vscode에서도 IDE level에서 린팅을 적용하려면 ./.vscode/settings.json
을 만들어 아래 값으로 세팅하면 된다.{
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.formatting.provider": "black",
"python.formatting.blackArgs": [
"--line-length",
"88"
],
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"python.linting.flake8Args": [
"--ignore=E203,E501,W503",
"--max-line-length=88"
]
}
만약 만든 프로젝트를 하나의 패키지로 묶어 라이브러리로 배포하려면 poetry build
와 poetry publish --build
를 진행하면 된다. 이 경우 https://pypi.org/ 의 계정이 필요하다!
이 단계에서 다양한 설정값이 필요할 수 있고 추가되면 좋은 정보도 많다. poetry 공식 깃허브 에서 해당 설정값을 확인하길 바란다!
참고로 이 toml
파일은 Tom's Obvious, Minimal Language
약자이며 "명확하고 읽기 쉬운 최소한의 구성 파일 형식을 목표" 로 하는 프로젝트 설정 설명 파일이다. ini
에서 영감을 받아서 발전되었다고 한다. PEP 518 – Specifying Minimum Build System Requirements for Python Projects 에서 pyproject.toml
파일을 이용해 패키지 빌드에 필요한 도구와 설정을 명세하고 이로써 Python 패키지의 빌드 프로세스를 표준화하고 있다.
더 나아가 PEP 621 – Storing project metadata in pyproject.toml 에서 파일에서 프로젝트 메타데이터를 정의하는 방법을 제안하고 있다. 이는 패키지의 이름, 버전, 설명, 저자 등의 정보를 TOML 형식으로 어떻게 하면 좋은지 적혀져 있다.
기본적으로 Poetry는 {cache-dir}/virtualenvs
디렉토리에 가상환경을 설정한다. 위에서 그대로 poetry shell
을 통해 가상환경에 진입하면 .../virtualenvs/my_project-ZdOTN-ZS-py3.9
와 같은 경로로 세팅되어 있는 것이 확인가능하다.
poetry env info
로 구성된 가상환경 확인이 가능하며 poetry env list
로 사용 가능한 가상환경 리스트를 볼 수 있다.
그리고 poetry env remove python3
와 같이 지금 세팅된 가상환경을 remove 할 수 있다. (python3 자리에는 우리가 사용하는 python 버전의 path, 심볼릭 링크 걸려있거나 path등록되어 있으면 당연히 python3 그대로 사용가능)
이렇게 자동 세팅되는 cache-dir
는 poetry config
명령어를 통해 임의로 설정할 수 있으며, virtualenvs.in-project
설정 변경을 통해 가상환경이 프로젝트 내에 위치하도록 할 수도 있다. poetry config virtualenvs.in-project true
와 같이 입력하고 poetry env use python3
을 입력하면 아래와 같이 깔끔하게 프로젝트 내부에 가상환경 파일을 위치시킬 수 있다.
poetry shell
로 지금 shell에서 가상환경에 붙었으면 deactivate
대신 exit
로 가상환경을 나오는 것이 좋다.# 의존성 설치
poetry install
# 개발환경의 의존성은 빼고 설치
poetry install --no-dev
# -E 또는 --extras 로 추가 의존성을 설정가능
poetry install --extras "mysql redis"
poerty install -E mysql -E redis
poetry.lock이 없을 때
: poetry install
명령어를 입력한 적이 없고, poetry.lock
파일이 없는 경우에, Poetry는 pyproject.toml
에 기록된 의존성들을 최신 버전의 다운로드를 통해 설치한다. 설치가 끝났을 때는 다운로드 받은 패키지들의 버전 정보를 이용하여 poetry.lock
파일을 생성한다. 해당 프로젝트를 사용하는 모든 사용자들이 같은 버전의 의존성을 사용할 수 있도록 poetry.lock을 반드시 커밋해야 한다.
poetry.lock이 있을 때
: poetry.lock
있으나 없으나 pyproject.toml
을 사용하여 의존성 정보를 확인하여 설치하지만, poetry.lock
파일이 존재할 경우 해당 파일에 나열된 정확한 버전을 설치해서 해당 프로젝트를 작업하는 모든 사용자의 의존성 버전이 일치하도록 한다. 결과적으로 pyproject.toml
에 나열되어 있는 모든 의존성을 해결하지만, 모든 의존성이 최신 버전이 아닐 수도 있다. 이는 의도치 않은 의존성 버전의 변경으로 인해 프로젝트가 망가지지 않도록 하기 위한 것이다.
poetry add django
# 개발환경에서 필요한 패키지 설치
poetry add --group dev pytest
# 버전을 지정가능
poetry add django@^3.0.0
poetry add "django=3.0.0"
# 최신버전을 설치
poetry add django@latest
# 깃 저장소에 있는 패키지 설치
poetry add git+https://github.com/django/django.git
# 깃 저장소의 패키지에서 브랜치를 지정
poetry add git+https://github.com/django/django.git#stable/2.2.x
# 로컬에 디렉토리의 파일로 설치하기
poetry add ./my-package/
poetry add ./my-package/dist/my-package-0.1.0.tar.gz
poetry add ./my-package/dist/my-package-0.1.0.whl
add
로 패키지를 추가(설치) 했으면 remove
로 패키지 제거(석제)를 할 수 있다.poetry remove pendulum
poetry remove mkdocs --group docs # 특정 그룹에 속한 패키지 삭제
# 패키지 업데이트
poetry update
# 하나씩 지정해서 업데이트도 가능
poetry update requests toml
# 업데이트는 하지 않고 poetry.lock 만 업데이트
poerty update --lock
# 설치된 모든 패키지를 보여준다.
poetry show
# 개발환경용 제외하고 보여준다.
poetry show --no-dev
# 특정패키지를 지정하면 상세내용을 보여줍니다.
poetry show django
# 최신 버전을 보여준다.
poetry show --latest (-l)
# 업데이트를 해야하는 패키지들을 보여준다.
poetry show --outdate (-o)
# 의존성 트리를 보여준다.
poetry show --tree
# 설정보기
poetry config --list
# 설정법
poetry config [options] [setting-key] [setting-value1] ... [setting-valueN]
poetry export -f requirements.txt > requirements.txt