지난 번 CentOS에 Python3.6 설치하기에서 기본 런타임 설치에 대해 간단히 소개를 했지만 실제로 Python을 이용한 서비스 환경을 구축하기 위해서는 좀 더 정교한 설정이 필요합니다.
우선 Python 런타임 버전에 민감한 애플리케이션이 아니라면 기본적으로 설치된 Python3 런타임을 PATH 환경변수에 추가해서 사용하면 됩니다. 그러나 서비스 환경에서는 외부 라이브러리 의존성 관리라든가 동일한 호스트에서 다른 버전의 런타임의 필요성 등이 민감한 문제가 될 수 있습니다.
Python 생태계에서 인기있는 도구들이 몇 가지 있습니다. venv, virtualenv, pyenv, pyenv-virtualenv, virtualenvwrapper, pipenv 등등. 인터넷에 여러가지 도구에 대한 설명들이 있으나 유행이 지나간 도구와 방법에 대한 내용이 많습니다. 이런 것들은 신경쓰지 않고 새로운 도구들(pyenv, pipenv)의 활용법을 중점적으로 다루겠습니다.
애플리케이션마다 요구사항이 좀 다를 수 있으니 단계별로 살펴보겠습니다. 만약 복잡하게 느껴진다면 3번과 4번만 읽어보셔도 됩니다.
1번의 경우, 특별한 도구가 필요하지 않습니다. 셸의 환경변수 PYTHONPATH를 이용하면 됩니다.
export PYTHONPATH=내가_만든_파이썬_라이브러리가_설치되는_경로
콜론( 기호를 구분자로 해서 여러 경로를 지정하면 Python 런타임이 import할 때 이 환경변수에 지정한 순서대로 모듈을 탐색합니다.
외부 Python 라이브러리는 버전을 잘 관리해야 하므로 Python 런타임 패키지에 포함되는 pip를 이용합니다. 3.x 버전에서는 pip3라는 이름으로 제공되고 있으므로 명시적으로 pip3로 실행해도 되고 PATH 환경변수로 런타임 경로가 잘 지정되어 있으면 pip으로도 실행해도 됩니다.
초기에 외부 Python 라이브러리를 설치할 때는, 우선 검색을 해볼 수 있습니다. 다음 명령을 이용할 수도 있는데 보통 너무 많은 검색 결과가 나오는 편이니 grep을 필터로 걸어서 볼 필요가 있습니다.
pip3 search 라이브러리_이름
PyPI 웹사이트에서 찾아볼 수도 있습니다. https://pypi.org/
다음 명령으로 설치 가능합니다. (하지만 실제로 뭔가 설치하지는 맙시다. 그 이유는 아래에서 다루겠습니다.)
pip3 install 라이브러리_이름
이렇게 설치된 라이브러리는 버전을 잘 관리하는 게 좋습니다. 특히 서비스가 안정적으로 지속되려면 버전은 특정 버전으로 고정하는 게 좋습니다. 아래 두 명령행은 기억해둘 필요가 있습니다.
pip3 freeze > requirements.txt
requirements.txt는 git에 포함시켜서 관리할 필요가 있습니다. 이 설정 파일을 이용해서 새로운 환경에서 동일하게 라이브러리를 재설치할 수 있습니다.
pip3 install -r requirements.txt
여기까지가 pip의 기본적인 사용법입니다. Python 개발을 해봤다면 누구나 알고 있는 내용입니다. 그러나 pip으로 외부 라이브러리를 설치하게 되면 /usr 하위에 설치해야 하니 root 권한도 필요하고 시스템 공통 환경에 영향을 주기 때문에 서비스용으로는 쓰는 서버에서는 리스크가 커지게 됩니다. (pip3 install은 가급적 피하는 게 좋습니다.)
예전에는 virtualenv이 표준적인 방법이었으나 좀 더 현대적인 도구인 pyenv와 pipenv로 대체 가능하니 virtualenv에 대한 설명은 간단하게 하고 넘어가겠습니다.
원리는 간단합니다. 현재 사용 가능한 Python 런타임을 디렉토리 째로 내 디렉토리에 복사해두고 그걸 마치 전역적인 런타임인 것처럼 사용하는 방법입니다.
virtualenv는 Python의 외부 라이브러리 의존성을 분리해서 사용할 수 있게 한 최초의 시도입니다. 오래된 방법이긴 하지만 환경 분리라는 개념은 모두 여기에서 출발했다고 할 수 있습니다.
이제 virtualenv는 잊고 pipenv를 사용하겠습니다. pipenv는 virtualenv의 공식적인 계승자라고 할 수 있습니다.
우선 다음과 같이 설치합니다.
pip3 install pipenv
pipenv는 requirements.txt 대신에 Pipfile과 Pipfile.lock으로 의존성을 관리합니다.
초기화를 합니다. 이 명령은 복원할 때도 동일하게 사용됩니다.
pipenv install
가상환경을 활성화합니다.
pipenv shell
외부 라이브러리를 설치해보겠습니다.
pipenv install beautifulsoup4
pip list
삭제합니다.
pipenv uninstall beautifulsoup4
pip list
pip freeze와 동일한 명령입니다. Pipfile.lock 파일을 생성하면서 런타임과 하위 의존성을 포함한 모든 의존성에 대한 정보를 기록해두기 때문에 완벽하게 동일한 환경을 재구축할 수 있게 해줍니다.
pipenv lock
이 명령 실행 후에는 Pipfile과 Pipfile.lock을 git에 commit하는 게 좋겠습니다.
Pipfile과 Pipfile.lock을 가지고 동일한 의존성 환경을 복원하려면 초기화에 사용했던 install을 실행하면 됩니다.
pipenv install
여러가지 이유로 런타임을 분리하는 게 필요할 수 있습니다. 예를 들면, 같은 호스트에서 어떤 애플리케이션은 Python 3.5 버전을 필요로 하고 또 다른 애플리케이션은 Python 3.7을 필요로 한다면 두 벌의 런타임을 설치해야 하는 어려움이 생깁니다. 시스템 경로에 Python을 버전별로 설치하는 건 현실적으로 어렵고 바람직하지도 않습니다.
또는, 런타임에 이름을 붙여서(추상화해서) 관리를 하고 싶은 경우가 있습니다. 이런 경우에 pyenv와 pyenv-virtualenv를 활용하면 편리합니다.
다음 명령을 실행하여 홈디렉토리 하위에 .pyenv를 설치합니다.
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
pyenv를 실행할 수 있도록 환경변수로 추가하는 설정을 .bashrc에 적어 줍니다.
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
이제 pyenv를 사용할 준비는 끝났습니다.
pyenv로 원하는 Python 런타임을 골라서 나만의 Python 실행 환경을 만들어보도록 하겠습니다.
우선 어떤 런타임 버전을 설치할 수 있는 리스트를 뽑아 봅니다.
pyenv install -l
2019년 4월 기준으로 가장 최신 버전은 3.7.3이 존재합니다. 이걸 설치해봅니다. 소스코드를 내려받아서 빌드하기 때문에 gcc 패키지와 make 패키지가 설치되어 있어야 합니다. 필수 라이브러리인 libffi-devel, zlib-devel과 openssl-devel 패키지도 미리 설치되어 있다고 가정합니다. 이전 글에서는 소스 빌드이 상당히 복잡하기 때문에 추천하지 않았으나 pyenv로 설치할 때는 필수 패키지만 잘 설치되어 있다면 큰 문제없이 자동으로 소스 빌드가 성공합니다.
pyenv install 3.7.3
설치가 완료되고 나면 설치된 상황을 확인할 수 있습니다.
pyenv versions
* system (set by /home/test/.pyenv/version)
3.7.3
system과 3.7.3이 목록으로 나올 겁니다.
이렇게 설치된 런타임은 ~/.pyenv 하위에 설치되어 있을 뿐 곧바로 사용할 수 있는 건 아니어서 특정 런타임을 골라서 활성화하는 과정이 한 번쯤은 필요합니다. (아래 명령은 옛날 방식이니 따라할 필요 없습니다.)
pyenv shell 3.7.3
pyenv activate
# python runtime 사용
pyenv deactivate
아무래도 이런 명령을 기억했다가 매번 입력해서 사용하는 것은 불편합니다. 다음의 방법으로 번거로운 과정을 모두 생략한 채 사용할 수 있습니다.
중요: 특정 디렉토리 하위에서 특정 런타임과 외부 라이브러리 의존성을 별도로 분리해서 자동으로 적용되도록 할 수 있습니다.
pyenv local 3.7.3
이 명령이 실행되면 해당 디렉토리에 .python-version 파일이 생성되고 여기에 버전을 기록해둡니다. 이후에도 그 디렉토리와 그 하위로 진입할 때마다 버전 3.7.3의 런타임이 자동으로 활성화됩니다. 그 디렉토리를 빠져나오면 자동으로 비활성화되고 전역적으로 사용하는 런타임이 선택됩니다. 이게 pyenv의 최대 장점이라고 할 수 있습니다.
자신이 사용하는 런타임 버전을 확인하고 싶다면 다음 명령으로 확인 가능합니다.
pyenv version
전역적으로 사용하는 런타임은 기본적으로 버전 2.7.5이고 system이라는 이름으로 통용됩니다. 만약 전역적으로 사용하는 런타임을 버전 3.7.3으로 변경하겠다면 다음 명령을 실행할 수 있습니다.
pyenv global 3.7.3
2.7.5로 되돌리고 싶다면...
pyenv global system
pyenv의 사용방법이 복잡해 보일 수 있어서 요약정리해 봅니다. 다음 세 가지 명령만 기억하면 됩니다. 그 중에서 가장 중요한 건 local 명령입니다.
설치: pyenv install 3.7.3
특정 디렉토리의 버전 지정: pyenv local 3.7.3
버전 확인: pyenv version
pyenv를 확장해서 virtualenv 기능을 사용할 수 있습니다. pyenv-virtualenv라는 멋진 도구가 있습니다.
다음과 같이 설치합니다.
git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
.bashrc 파일에 pyenv 설정을 추가한 것처럼 pyenv-virtualenv 초기화 설정을 추가합니다. (두번째 eval 문장)
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
fi
이제 위에서 설치했던 3.7.3 환경에 다른 이름으로 달아두고 사용합니다. v3라는 분리된 가상 환경을 얻었습니다.
pyenv virtualenv 3.7.3 v3
설치되어 사용가능한 버전들을 살펴봅니다.
pyenv versions
* system (set by /home/test/.pyenv/version)
3.7.3
3.7.3/envs/v3
v3
v3라는 이름의 가상 환경이 생긴 것을 확인할 수 있습니다. 하나만 만들어서 쓸거라면 굳이 가상 환경을 쓸 필요가 없습니다. 실제 환경 3.7.3은 한 벌만 설치해두고 가상 환경을 여러 벌로 만들어두면 분리된 환경으로 사용할 수 있습니다.
pyenv virtualenv 3.7.3 v3_test_env
pyenv versions
* system (set by /home/test/.pyenv/version)
3.7.3
3.7.3/envs/v3
3.7.3/envs/v3_test_env
v3
v3_test_env
이제 v3 환경과 v3_test_env 환경이 모두 3.7.3 런타임에 기반하지만 별도로 분리된 환경으로 준비되었습니다.
pyenv local을 이용하여 특정 디렉토리에서 사용할 가상 환경을 정합니다.
cd ~/my_work_dir
pyenv local v3
pip list
cd ~/my_test_dir
pyenv local v3_test_env
pip list
마찬가지로 이후에 해당 디렉토리에 들어갈 때마다 정해진 가상 환경이 자동으로 활성화됩니다.
혹시 Python 가상 환경의 버전을 변경해야 하는 경우, 신규 런타임을 pyenv install로 설치한 다음에 가상 환경을 지우고 다시 신규 런타임에 기반하도록 설정하는 것도 가능합니다.
pyenv install 3.7.4
pyenv versions
pyenv uninstall v3
pyenv virtualenv 3.7.4 v3
물론, 이런 업그레이드 작업 전에 pipenv lock을 이용해서 의존성 정보를 고정시켜둘 필요가 있습니다.
혹시 이 가상 환경에서 서비스 형태로 Python 애플리케이션이 실행 중이라면, 위와 같이 uninstall하기 어렵습니다. 이런 경우에는 별도 디렉토리에 신규 가상 환경을 구축하고 기존 서비스는 중지하고 신규 가상 환경에서 새롭게 서비스를 시작하는 게 좋습니다.
pyenv와 pyenv-virtualenv 조합에 pipenv를 곁들여서 사용하면 편리합니다.
git으로 pyenv 설치하고 pip3로 pyenv-virtualenv와 pipenv만 설치해두면 이후에는 /usr 하위에 외부 라이브러리나 도구를 설치할 필요가 없습니다.
pipenv도 상당히 편리한 도구이지만 개인적으로는 pyenv가 더 편리해서 이걸 추천하고 싶습니다. 환경을 분리하거나 자동 설정 적용으로 좀 더 편하게 사용하고 싶다면 pyenv를 선택하고, 런타임 분리는 필요없고 의존성만 분리하고 싶다면 pipenv를 선택하면 됩니다. pyenv는 런타임을 처음에 한 번은 소스 빌드해야 한다는 부담이 있고, pipenv는 실행할 때마다 shell 명령으로 활성화시키는 과정이 살짝 번거롭습니다.
풀 패키지로 한번에 모든 패키지를 포함해서 설치하고 싶다면 Anacoda를 추천합니다. yum이나 apt같은 시스템 패키지 관리자를 이용할 수도 있고 다운로드해서 설치할 수도 있습니다.
Anaconda는 런타임과 의존성을 미리 잘 패키징해두어서 쉽고 빠르게 설치해서 쓸 수 있는데, 주로 윈도우즈 환경이나 데이터 분석용으로 사용합니다.
conda라는 이름의 CLI 도구를 제공하는데 이걸 이용해서 가상 환경을 만들고 추가적인 패키지 설치가 가능합니다.
conda create -n my_ana_env
conda activate my_ana_env
conda install lxml
conda deactivate
pyenv 또는 pip과 거의 유사한 문법을 지원하므로 자세한 설명은 생략하겠습니다.
Anaconda는 패키지 구성이 잘 되어 있지만 상당히 크기 때문에 가벼운 환경에서는 작은 크기로 구성되어 있는 miniconda를 사용하기도 합니다. 마찬가지로 conda를 이용하여 추가적인 패키지 설치가 가능합니다.