티스토리 뷰

Poetry는 "Python dependency management and packaging made easy."라는 모토로 움직이는 파이썬 의존성 관리 프로그램이다. conda, pyenv 등이 설치되어 있다고 가정했을 때 poetry의 위치는 아래 그림과 같다. 글의 전반에 걸쳐 이야기하겠지만 poetry는 가상환경을 만들 때 현재 시스템에 적용되어 있는 환경을 가져다 사용한다. 즉, conda 3.7 환경에서 poetry를 돌리면 파이썬 3.7 버전으로 가상환경이 만들어질 것이고, pyenv 3.9가 적용되어 있는 터미널에서 poetry로 install 하면 파이썬 3.9 버전으로 가상환경이 만들어진다. - see more

 

# 주요 특징

- pip를 감추고 패키지와 디펜던시를 관리 함 ( 내부적으로는 사용 함 )
- 프로젝트별 가상환경을 자동으로 생성해줌 ( default: true )
- 단, 현재 터미널의 파이썬 버전으로 가상환경을 만들기 때문에 여러버전의 Python이 필요한 경우 pyenv, conda 등을 여전히 활용해야 함
- 백엔드 개발의 경우 같은 회사라면 python 버전을 대부분 통일해서 사용하겠지만,
- 오픈소스를 많이 활용하는 머신러닝의 경우 python 버전 디펜던시가 머신러닝 프레임워크, CUDA 등과 복잡하게 얽힌 경우가 많아서 다양한 버전의 python을 쓰는 경우가 꽤 있음.
- 하지만 머신러닝은 차라리 docker 환경에서 개발하는게 제일 낫더라는 (...)
- poetry는 2020-02-03 07:12 KST 기준으로 Star가 13.7k, release가 97번이나 된 인기 있는 프로젝트임에도 불구하고 여전히 베타 같은 느낌이 드는것도 주요 특징.

 

# TMI

poetry 명령어는 python 2.7, 3.5, 3.6, 3.7, 3.8, 3.9 환경에서만 지원 한다. 터미널에서 python -V 혹은 아래와 같이 프롬프트를 통해 을 통해 파이썬 버전을 확인하면 된다. 프롬프트 접속만 해도 이미 버전은 출력되지만 말이다.

>>> import sys 
>>> sys.version_info

poetry는 상당히 강력한 컨셉의 의존성 관리 툴이지만 시스템 파이썬의 버전에 따라 아직 불안정한 부분들이 보인다... 성장통일까? 아무튼, 혹시 터미널 명령어에서 오류가 나면 아래 경로에 가서 수정해서 써보자. 개발자라면 극복해야 하지 않겠나.

cd $(dirname $(which poetry))/../lib/poetry/console

기회가되면 contribution도...?
- https://github.com/python-poetry/poetry/tree/master/poetry/console
- pip가 GitHub에서 스타가 6.9k 인 것을 생각하면 poetry(13.7k)는 단순히 유행 정도가 아닌거다.
- 그렇다고 짐싸들고 옮겨가는 건 쉽지 않다.
- 이미 많은 개발자들이 이미 pip, requirements.txt 의 노예가 아니던가.

 

# Github Repo.

poetry 소스코드는 아래 레포지토리에서 확인하면 된다.
https://github.com/python-poetry/poetry

 

# 설치
https://python-poetry.org/docs/#installation

osx, linux

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


windows

(Invoke-WebRequest -Uri <https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py> -UseBasicParsing).Content | python -


pip로 설치
지원은 하지만 다른 패키지와 충돌이 발생할 수 있다고 공식적으로 권장하지 않는다.

pip install --user poetry

 

# poetry 다루기

프로젝트 셋업
my-project 부분에 프로젝트 이름을 넣어주면 된다. 이것만으로 기본적인 프로젝트 셋업이 끝난다.

poetry new my-project

poetry new를 진행하고 나면 기본 디렉터리 구조가 아래와 같이 자동으로 생성 된다.

$ tree
.
├── README.rst
├── my-project
│   └── __init__.py
├── pyproject.toml
└── tests
    ├── __init__.py
    └── test_my-project.py

2 directories, 5 files

위에처럼 디렉터리 구조를 생성하지 않고 의존성 관리 파일(pyproject.toml)만 생성하려면 init 옵션을 사용하면 된다. - pyproject.toml은 poetry 전용 requirements.txt 정도로 생각하면 된다.

poetry init

이미 소스코드가 poetry로 관리되고 있어서 pyproject.toml 파일이 있다면, 해당 파일에 정의된 패키지를 install 옵션을 통해 설치할 수 있다. 

poetry install

- pyproject.toml 파일에 명시된 의존성을 설치된다.
- 가상환경은 이때 생성 된다.
- 패키지가 설치되는 건 pip install -r requirements.txt 와 비슷한 느낌이다 (패키지별 디펜던시를 검사하는 부분에서 차이를 보임)
- npm install만 입력하면 package.json에 있는 의존성이 설치 되듯이 poetry install을 입력하면 현재 디렉터리에 pyproject.toml을 참조해서 패키지가 설치 된다.
- 조금 더 엄격히 이야기하면 poetry.lock 파일을 먼저 참고하고 해당 파일이 없으면 pyproject.toml을 바라보게 되지만, 이 글에서 poetry.lock 파일에 대한 언급은 하지 않기로 한다.

 

현재 환경 보기

poetry env info

아직 poetry install 되지 않은 상태라면 환경은 생성되지 않은 상태이다. 설치된 poetry 환경 목록은 env list 옵션으로 확인 할 수 있다.

poetry env list

- conda 등과 다르게 시스템에 설치된 전체 가상환경 목록을 보는 컨셉은 아니다.
- 프로젝트별로 환경이 관리되기 때문에 현재 프로젝트에 적용되는 환경만 볼 수 있다.
- 조금 더 상세한 예를 들자면 A, B 디렉터리가 존재하고 서로 다른 프로젝트가 진행되고 있을 때,
- A 디렉터리에서 poetry env list 를 실행한 결과와 B 디렉터리에서 실행한 결과가 다르다는 이야기이다.

다음으로는 poetry tab completion 설정을 알아보자.
https://python-poetry.org/docs/#enable-tab-completion-for-bash-fish-or-zsh

- aws, git ( git-completion.bash ) 명령어처럼 탭 자동완성을 지원 한다.
- 하지만... 1 depth 밖에 지원을 안해서 그닥 유용하진 않는다. ( help를 타이핑하는게 더 빠름... )
- 아무튼, 필요하면 각자의 셸 환경에 맞게 명령어를 터미널에서 실행하자.
- 한편, poetry 설치될 때 셸 환경 읽어서 자동으로 써줬으면 좋지 않았을까 하는 아쉬움이 남는다...
- 명령어는 아래를 참고하자.

# 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

본인 셸에 맞는 라인을 실행을 하고 아래 명령어로 현재 터미널 세션에 적용할 수 있다.

source $(brew --prefix)/etc/bash_completion.d/poetry.bash-completion

새로운 세션에도 적용이 필요한 경우 .bash_profile, .bashrc 등 본인의 환경에 맞게 추가해주면 된다. 아래는 관련 예시이다.

# .bash_profile
if [ -f $(brew --prefix)/etc/bash_completion.d/poetry.bash-completion ];then
    source $(brew --prefix)/etc/bash_completion.d/poetry.bash-completion
fi

이제 tab 동작을 확인해 보자.

$ poetry [tab]
about    build    check    debug    export   init     lock     publish  run      self     show     version
add      cache    config   env      help     install  new      remove   search   shell    update

만약, osx에서 poetry [tab] 을 눌렀을 때 다음과 같은 오류가 발생한다면,

poetry shbash: __ltrim_colon_completions: command not found

아래와 같이 bash-completion을 설치&적용하고 다시 poetry [tab]을 해보자.

brew install bash-completion source $(brew --prefix)/etc/bash_completion

내 컴퓨터에 자꾸 뭔가 설치 되는게 싫다는 사람은 .bash_profile 등에 __ltrim_colon_completions 함수를 등록하면 된다.

# .bash_profile
__ltrim_colon_completions()
{
    if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
        # Remove colon-word prefix from COMPREPLY items
        local colon_word=${1%"${1##*:}"}
        local i=${#COMPREPLY[*]}
        while [[ $((--i)) -ge 0 ]]; do
            COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
        done
    fi
}

 

가상 환경 삭제

- poetry env list에서 삭제할 이름을 [python name] 부분에 넣어주면 된다.
- 삭제할 환경 이름은 poetry env list, 혹은 poetry env info를 통해 확인하도록 하자.

poetry env remove [python name]  

아래는 예시이다.

(base) caleybaek$ poetry env info

Virtualenv
Python:         3.8.5
Implementation: CPython
Path:           /Users/caleybaek/Library/Caches/pypoetry/virtualenvs/test-bArR8eff-py3.8
Valid:          True

System
Platform: darwin
OS:       posix
Python:   /Users/caleybaek/anaconda3
(base) caleybaek$
(base) caleybaek$ poetry env remove test-bArR8eff-py3.8
Deleted virtualenv: /Users/caleybaek/Library/Caches/pypoetry/virtualenvs/test-bArR8eff-py3.8

혹시 어떤 이유로든 삭제가 되지 않는다면 위엥서 확인된 Path를 그냥 지워버리면 된다.

rm -rf /Users/caleybaek/Library/Caches/pypoetry/virtualenvs/test-bArR8eff-py3.8

 

# 현재 가상환경에 설치된 패키지 목록 확인

위에서 언급했지만 가상환경은 프로젝트(디렉터리) 별로 관리되기 때문에 poetry init, poetry install이 실행된 디렉터리, 혹은 그 하위 디렉터리 트리에서 동작한다는 점을 참고하자.

poetry show

패키지 트리까지 보려면 뒤에 --tree 옵션을 사용하면 된다.

poetry show --tree

 

# 설치된 패키지 중에 특정 항목 상세 보기

poetry show 뒤에 패키지명을 적어주면 된다. 아래는 pytest 패키지의 디펜던시를 살펴보는 예시이다.

$ poetry show pytest
name         : pytest
version      : 6.2.2
description  : pytest: simple powerful testing with Python

dependencies
 - atomicwrites >=1.0
 - attrs >=19.2.0
 - colorama *
 - iniconfig *
 - packaging *
 - pluggy >=0.12,<1.0.0a1
 - py >=1.8.2
 - toml *

 

신규 패키지 설치

https://python-poetry.org/docs/cli/#add

add 옵션을 사용해서 패키지를 설치할 수 있다. pip 에서 pip install pendulum@latest 처럼 사용하는 것과 동일하다.

poetry add pendulum@latest

- 명령어 실행 시 pyproject.toml 에 패키지가 먼저 추가되고 설치가 시작 된다.
- 아래와 같이 특정버전, 특정 리비전, git url 등을 인자로 넘길 수 있다.

 

설치된 패키지 제거

remove 옵션으로 패키지를 제거할 수 있다.

poetry remove pendulum

 

가상환경으로 진입

shell 옵션을 사용해서 가상환경으로 진입할 수 있다. 아직 install 전이라서 가상환경이 없는 경우에는 환경이 새로 생성 된다.

poetry shell

아래 예시를 살펴보면 시스템에 설치된 파이썬은 3.8.5인데 poetry shell로 진입해서 보면 가상환경의 파이썬 버전이 확인된다.

(base) caleybaek:tmp$ python
Python 3.8.5 (default, Sep  4 2020, 02:22:02)
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
(base) caleybaek:tmp$ poetry shell
Spawning shell within /Users/caleybaek/Library/Caches/pypoetry/virtualenvs/caley-test-jhaiyYQK-py3.8
bash-3.2$ . /Users/caleybaek/Library/Caches/pypoetry/virtualenvs/caley-test-jhaiyYQK-py3.8/bin/activate
(caley-test-jhaiyYQK-py3.8) bash-3.2$
(caley-test-jhaiyYQK-py3.8) bash-3.2$ python
Python 3.8.1 (default, Feb  2 2021, 13:25:15)
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

 

${HOME} /Library/Caches 경로가 불편하다면…

프로젝트(현재 디렉터리) 경로에 가상환경을 생성할 수 있다. 그렇게 하려면 아래와 같이 virtualenvs.in-project 옵션을 true로 설정해주면 된다.

poetry config virtualenvs.in-project true

--list 옵션으로 다른 설정을 확인해놓으면 나중에 뭔가 필요할 때 대처가 쉽기 때문에 --list 옵션으로 미리 둘러보자.

$ poetry config --list
cache-dir = "/Users/caleybaek/Library/Caches/pypoetry"
experimental.new-installer = true
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = true
virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/caleybaek/Library/Caches/pypoetry/virtualenvs

 

poetry로 생성될 가상환경의 python 변경

아래처럼 use 다음 인자로 사용할 python 의 경로를 지정할 수 있다. conda, pyenv 등으로 다양한 python 환경을 만들어놓고 지정해서 활용하면 된다.

poetry env use /Users/caleybaek/.pyenv/shims/python

 

# PyCharm 설정

Preferences - Plugins에서 poetry를 검색하고 설치하자. 설치가 끝나면 PyCharm을 재시작 해준다. ( Restart IDE )

재시작이 완료되면 아래처럼 Interpreter 목록에 Poetry Environment를 확인할 수 있다.

Existing enviroment를 선택하고 경로는 터미널에서 아래와 같이 poetry env info 명령어 결과의 Path 부분 참고하면 된다.

$ poetry env info

Virtualenv
Python:         3.8.5
Implementation: CPython
Path:           /Users/caleybaek/Library/Caches/pypoetry/virtualenvs/test-bArR8eff-py3.8
Valid:          True

System
Platform: darwin
OS:       posix
Python:   /Users/caleybaek/anaconda3

 

끝으로 앞서 Poetry의 불안정함에 대해서 잠시 언급했는데 내 경우 grpcio 설치에서 한참을 애먹었다. 이미 OSX Big Sur에서 나와 동일한 이슈를 여럿이 겪고 있었고 다른 사람들의 해결 방법은 내게 도움이 되지 못했다. 오히려 시스템 파이썬의 micro 버전을 올리니까 해결되서 ... 그때의 허무함이란.......

poetry .. 의심해서 미안해요

 


 

마무리

poetry가 딱히 pip + env(pyenv, conda, etc..)를 대체한다는 메리트는 못찾겠다... 환경을 뚜렷하게 구분할 때는 차라리 container로 운영하는 게 나아서.... 디렉터리에 들어가면 바로 환경이 세팅된다는 점? 글쎄.. 대부분이 파이썬 개발자는 터미널 사용할 일이 잦지 않고 어차피 IDE 사용하는 입장이지 않을까? ML 쪽은 서빙이나 쥬피터를 가상환경 안에서 띄워야할테니 조금은 메리트가 되려나. 환경이 자동으로 세팅되기 때문에 구성원간에 환경을 맞추는게 용이하다? 이것도 글쎄... 어차피 개발은 python 버전 맞추고 시작하는 부분이라... 아래 장점처럼 사용하는 사람(조직)에게는 유용할수도 있겠다. 개인적으로 conda는 (1차) 가상환경을 만들기 위해서 계속 사용할 듯. 고로 conda+poetry 조합으로 사용하는게 편하다. e.g.) conda로 3.9.0 버전의 가상환경(A)을 만들고 poetry로 A를 이용해서 가상환경 B, C, D를 만들어 쓰는 구조이다.

장점

프로젝트 대부분이 파이썬 특정 버전을 사용하는 경우 poetry가 장점이 될 수 있다. 예를 들어 모든 프로젝트가 3.8.1 버전을 사용한다고 했을 때 콘다의 경우 매번 아래처럼 환경을 만들어줘야겠지만,

$ conda create --name PROJECT_AAA_P381 python=3.8.1
$ conda create --name PROJECT_BBB_P381 python=3.8.1
$ conda create --name PROJECT_CCC_P381 python=3.8.1

poetry의 경우 3.8.1 버전으로 기본 시스템의 파이썬 버전을 맞춰 놓으면 poetry install 만으로 환경이 자동으로 세팅된다 (어차피 내부적으로 3.8.1 을 가져다가 가상 환경을 만드는건 똑같지만 타이핑 몇 개 생략해서 귀차니즘이 줄어든다는 정도). 콘다의 경우 세팅된 환경이 프로젝트(디렉터리)를 넘어서 시스템 전체에 적용되기 때문에 pip install 한번 잘못 치면 나중에 pip freeze로 솎아내는데 골머리 앓을수도 생긴다... 반면 poetry는 프로젝트(디렉터리) 단위로 움직이기 때문에 그런 걱정이 없다.

단점

장점을 쥐어짜낸 것처럼 단점도 굳이 찾자면... 현재 프로젝트의 파이썬 버전을 바로 확인할 수 없다. 콘다의 경우 PS1 앞에 현재 적용된 환경 이름이 붙기 때문에 가시적으로 좋았는데..

(test-server) caleybaek:console$

개인적으로 상당히 불편하다. pyenv를 사용하지 않는 것도 이것 때문에...

댓글
최근에 올라온 글
최근에 달린 댓글
글 보관함
Total
Today
Yesterday