파이선 가상환경 콘다 시작하기

콘다는 언어의 패키지, 의존관계와 환경을 관리하는 툴입니다. 지원하는 언어는 파이선, R, 스칼라, 자바, 자바스크립트 등이 있다고 하는데 이 글에서는 실제로 사용해본 것은 파이선 중심으로 설명하도록 하겠습니다.

1. 배경

언어 스팩은 쉽게 변하지 않는 핵심 사상을 표현하는 이상이라고 한다면, 추가 패키지는 살기위해 먹고, 마시고, 돈을 벌어야 하는 현실이라고 할 수 있겠죠. 언어 스팩만으로 원하는 제품이나 서비스를 만드는 것은 학교 숙제를 할 때를 제외하고는 해본 적이 없습니다. 우리 모두는 현실의 업무 환경에서 운영체제의 시스템 API (Win32 API, 리눅스 API)와 플랫폼 혹은 프레임워크 (안드로이드, 스프링, 닷넷), 라이브러리 (logback, scikit) 등 다른 이가 작성한 코드의 힘을 입어 개발하고 있습니다. 하지만, 그렇기 때문에 마치 우리의 인생이 현실의 불합리로 괴로워하듯 우리가 만드는 제품이나 사용하고 싶은 패키지들은 언어의 버전 혹은 다른 패키지들과의 의존 관계에 괴로워합니다. 태초에 윈도우에는 DLL HELL이 개발자들을 울렸다면, 파이선은 2.x 대 버전과 3.x 버전 사이의 차이로 거의 10년간 개발자들을 헷갈리게 하고 있습니다.

2. 가상환경 관리자, 콘다

현실이 가장 직관적인 해결방법은 모든 운영환경에 설치된 가장 낮은 버전의 파이선 배포본을 사용하는 것입니다. 예를들어 2013년 12월에 릴리즈한 센트OS 6.5버전에서는 파이선 2.6이 기본 파이선 패키지입니다. 참고로 파이선 2.7버전은 2010년 7월에 릴리즈 했습니다. 개발용으로 지급받은 최신 맥북 프로에 파이선 2.6을 설치하고 있는 자신을 상상해보세요! 그리고 그런 감정을 다시 느끼지 않을 (혹은 덜 느낄) 방법이 있습니다. 가상 환경 관리자를 사용하는 것입니다.

가상환경 관라자들의 기본 원리는 단순합니다. 버전에 맞는 환경변수 그룹을 만들어서 이름을 부여하고, 그룹마다 지정된 경로에 패키지를 설치하고 참고하는 것입니다. 다른 환경변수 그룹으로 이동하면 전혀 다른 패키지들을 보게 되는거죠. 이런 환경변수 그룹을 가상환경 (virtual environment)이라고 부릅니다.

이런 작업을 해주는 툴을 가상환경 관리자라고 하며, 가장 널리 사용되는 것으로 virtualenv, 콘다(conda)가 있습니다. virtualenv에 관한 자료는 한글로 작성된 좋은 자료들이 많이 있으니 저는 콘다에 대해 더 알아보겠습니다.

3. 미니콘다

콘다는 아나콘다와 미니콘다로 나뉘는데, 콘다는 패키지 매니져이고, 미니콘다는 콘다를 사용하는 최소한의 설치 패키지이고 아나콘다는 (2017년 1월 현재) 720개 이상의 주요 패키지를 한꺼번에 설치해주는 패키지입니다.

아나콘다와 미니콘다 선택 기준

둘 다 설치 이후의 사용 방법은 동일합니다. 둘의 간략한 차이를 보고 마음에 드는 콘다를 설치하세요.

미니콘다 내려받기 아나콘다 내려받기
- 개별 패키지를 각각 설치하는데 거부감이 없거나 - 콘다 혹은 파이선에 익숙하지 않거나
- 아직 사용여부를 모르는 패키지를 설치하는데 디스크 공간이 부족하거나 시간이 아까워서 - 파이선과 함께 한번에 주요 패키지를 자동적으로 설치하고 싶거나
- 빠르게 파이선과 콘다를 설치해서 사용해보고 싶다면 - 디스크 공간이 충분하다면 (3기가 이상)

4. 맥 OS X 또는 리눅스에 미니콘다 설치

  1. 설치 파일 내려받기 미니콘다 사이트에서 각자 운영체제와 설치된 파이선 버전에 맞는 설치 파일을 내려받습니다.

  2. 설치 파일 실행하기 설치는 yes 와 enter를 입력하면 간단하게 완료됩니다.

    $ bash Miniconda3-latest-Linux-x86_64.sh
  3. 실행 경로 추가

    설치 마지막에 미니콘다 경로가 자동으로 .bash_profile 에 복사되어 들어갑니다. 하지만 bash를 제외한 다른 쉘은 기본으로 지원하지 않으므로 zsh를 사용하는 경우 아래 내용을 $HOME/.zshrc 파일에 추가합니다. $HOME/miniconda3는 기본값으로 설치한 미니콘다의 경로이므로 혹시 설치 과정에서 다른 경로에 설치했다면 그에 맞게 경로를 설정해야합니다.

    export PATH=$HOME/miniconda3/bin:$PATH
  4. 설치 확인

    source 명령을 통해 변경한 설정을 현재 터미널에 반영한 후 conda 명령이 동작하는지 확인합니다.

    $ source ~/.bash_profile
    $ conda list
    # packages in environment at /home/ubuntu/miniconda3:
    #
    conda                     4.2.12                   py35_0
    conda-env                 2.6.0                         0
    openssl                   1.0.2j                        0
    pip                       8.1.2                    py35_0
    pycosat                   0.6.1                    py35_1
    pycrypto                  2.6.1                    py35_4
    python                    3.5.2                         0
    readline                  6.2                           2
    requests                  2.11.1                   py35_0
    ruamel_yaml               0.11.14                  py35_0
    setuptools                27.2.0                   py35_0
    sqlite                    3.13.0                        0
    tk                        8.5.18                        0
    wheel                     0.29.0                   py35_0
    xz                        5.2.2                         0
    yaml                      0.1.6                         0
    zlib                      1.2.8                         3
    $ conda update conda

5. 사용 예

그럼 실제 개발환경을 구축하는 과정을 경험해 보겠습니다. 우선은 널리 사용되는 파이선 웹 프레임워크인 플라스크(flask)와 MySQL을 사용하는 개발환경을 만들어보겠습니다.

5.1 새로운 개발 환경 만들기

새로운 콘다 환경을 만드는 방법은 conda create --name $ENVIRONMENT_NAME $PREINSTALL_PACKAGES 입니다. $ENVIRONMENT_NAME은 원하는 이름을 $PREINSTALL_PACKAGES은 기본으로 설치할 패키지를 의미합니다. 아래는 webdev라는 이름의 환경을 flask 패키지가 설치된 상태로 만드는 예입니다.

[email protected]:~$ conda create --name webdev flask
Fetching package metadata .......
Solving package specifications: ..........

Package plan for installation in environment /home/ubuntu/miniconda3/envs/webdev:

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    xz-5.2.2                   |                1         669 KB
    python-3.6.0               |                0        16.3 MB
    click-6.7                  |           py36_0         105 KB
    itsdangerous-0.24          |           py36_0          19 KB
    markupsafe-0.23            |           py36_2          35 KB
    setuptools-27.2.0          |           py36_0         523 KB
    werkzeug-0.11.15           |           py36_0         430 KB
    wheel-0.29.0               |           py36_0          88 KB
    jinja2-2.9.4               |           py36_0         334 KB
    pip-9.0.1                  |           py36_1         1.7 MB
    flask-0.12                 |           py36_0         104 KB
    ------------------------------------------------------------
                                           Total:        20.2 MB

The following NEW packages will be INSTALLED:

    click:        6.7-py36_0
    flask:        0.12-py36_0
    itsdangerous: 0.24-py36_0
    jinja2:       2.9.4-py36_0
    markupsafe:   0.23-py36_2
    openssl:      1.0.2j-0
    pip:          9.0.1-py36_1
    python:       3.6.0-0
    readline:     6.2-2
    setuptools:   27.2.0-py36_0
    sqlite:       3.13.0-0
    tk:           8.5.18-0
    werkzeug:     0.11.15-py36_0
    wheel:        0.29.0-py36_0
    xz:           5.2.2-1
    zlib:         1.2.8-3

Proceed ([y]/n)? y

원하는 패키지가 맞는지 검토하고 y를 입력해서 설치를 마치면 webdev 환경에 들어갈 수 있습니다. 환경으로 들어가는 콘다 명령은 source activate $ENVIRONMENT_NAME입니다.

[email protected]$ source activate webdev
(webdev) [email protected]:~$ 

프롬프트 맨 앞에 환경 이름 (webenv)가 있는 것을 확인할 수 있습니다. 콘다는 (virtualenv 도) 이렇게 프롬프트 맨 앞에서 환경 이름을 보여줌으로 실수를 줄여줍니다. 설치가 정상적으로 완료되었는지 확인하기 위해 현재 설치된 패키지 목록을 보여주는 conda list 명령을 내립니다.

(webdev) [email protected]:~$ conda list
# packages in environment at /home/ubuntu/miniconda3/envs/webdev:
#
click                     6.7                      py36_0
flask                     0.12                     py36_0
...

그럼 플라스크에서 MySQL을 사용하기 위해 flask-mysql 모듈을 설치하겠습니다.

(webdev) [email protected]:~$ conda install -c auto flask-mysql
Fetching package metadata .........
Solving package specifications: ....

UnsatisfiableError: The following specifications were found to be in conflict:
  - flask-mysql
  - python 3.6*
Use "conda info <package>" to see the dependencies for each package.

실패했습니다. 무엇이 문제일까요? 모듈과 파이선 버전이 충돌이 발생했습니다. 찾아보니 flask-mysql 사용하려던 flask-mysql 모듈은 파이선 2.x에서 동작하는군요. conda는 새로운 환경을 만들 때 현재 파이선 버전을 따라가는데 제 개발환경의 파이선이 3.5.2 버전이어서 webdev도 동일하게 만들어졌네요. 그럼 이번엔 파이선 2.7 버전이 설치된 환경 webdev27을 만들어보겠습니다.

(webdev) [email protected]:~$ conda create --name webdev27 python=2.7 flask

pip 사용법과 동일하게 $패키지이름=$버전 형식으로 특정 버전의 패키지를 설치할 수 있습니다.

새로 만들어진 환경으로 이동하려면 마찬가지로 source activate $ENVIRONMENT_NAME 명령을 내립니다. 환경에서 나왔다가 다른 환경으로 들어갈 필요없이 바로 이동할 수 있습니다.

(webdev) [email protected]:~$ source activate webdev27
(webdev27) [email protected]:~$ python --version
Python 2.7.13 :: Continuum Analytics, Inc.

파이선 2.7 버전이 설치 된 것도 확인했으니 이제 다시 flask-mysql을 설치합니다.

(webdev27) [email protected]:~$ conda install flask-mysql
Fetching package metadata .......
Solving package specifications: .


PackageNotFoundError: Package not found: '' Package missing in current linux-64 channels:
  - flask-mysql

You can search for packages on anaconda.org with

    anaconda search -t conda flask-mysql

You may need to install the anaconda-client command line client with

    conda install anaconda-client

이건 또 뭘까요? 또 실패했습니다. 매시지를 읽어보니 패키지를 찾을 수 없다고 나오는데요, 찾아보니 이 패키지가 기본 채널(리포지토리와 유사한 개념)에 존재하지 않기 때문에 발생한 문제입니다. 이번엔 채널을 자동으로 찾아주는 -c auto 플래그를 추가해줍니다. 더 자세한 내용은 콘다 패키지 관리 항목을 참고하세요.

(webdev27) [email protected]:~$ conda install -c auto flask-mysql

혹은, 여기서 pip install flask-mysql 명령으로 설치해도 동일합니다. pip 명령으로 설치되는 패키지도 conda의 환경안에서 동작하기 때문에 condapip를 함께 사용할 수 있습니다. 나중에 함께 볼 conda env export 명령으로 pip로 설치된 패키지가 conda 환경에 포함된 것도 확인할 수 있습니다.

개발을 마치면 source deactivate 환경에서 빠져나옵니다.

(webdev27) [email protected]:~$ source deactivate
[email protected]:~$

프롬프트 변경으로 webdev27 환경에서 나온 것을 확인했습니다.

5.2 반복하기

자 마침 팀장이 지나가다가 여러분이 제품에 맞는 파이선 환경을 척척 만들어내는 것을 보고 칭찬을 합니다.

서팀장: 우와~ 팀원들이 이 문제로 얼마나 고생을 하고 있었는데, 문개발님이 해결해주셨네요. 인상적입니다.
문개발: 뭐 어려운 일도 아닌데요. 이 정도는 누구나 금방 적용할 수 있습니다. (으쓱)

그리고 칭찬에 이은 한 마디

서팀장: 마침 우리가 플라스크 웹 앱을 배포해야하잖아요. 새로 도입하는 100대 가상머신을 어떻게 설정하나 고민했는데 문개발님이 해주시면 좋겠네요. 어려운 건 아니죠?
문개발: (동공지진) 그.. 그럼요..

친숙한 상황아니신가요? 아니시라면 부럽네요. 하지만, 우리는 쉽게 위기를 극복할 수 있습니다. 콘다는 반복 작업의 명시적으로 수행할 수 있도록 설정파일을 제공합니다.

앞에서 잠깐 살펴보았던 conda-env 명령을 이용해서 현재 환경을 내보내고,

(webdev27) [email protected]:~$ conda-env export -f env.yml

가상환경을 만드는 conda create 명령에 -f env.yml 인자를 통해 동일한 가상환경을 만들수 있습니다.

conda env create -f env.yml

env.yml 파일은 아래의 구조를 가지고 있습니다.

name: webdev27
channels: !!python/tuple
- defaults
dependencies:
- auto::flask-mysql=1.2=py27_0
- click=6.7=py27_0
- flask=0.12=py27_0
- itsdangerous=0.24=py27_0
- jinja2=2.9.4=py27_0
- markupsafe=0.23=py27_2
- mysql-python=1.2.5=py27_0
- openssl=1.0.2j=0
- pip=9.0.1=py27_1
- python=2.7.13=0
- readline=6.2=2
- setuptools=27.2.0=py27_0
- sqlite=3.13.0=0
- tk=8.5.18=0
- werkzeug=0.11.15=py27_0
- wheel=0.29.0=py27_0
- zlib=1.2.8=3
prefix: /home/ubuntu/miniconda3/envs/webdev27

5.3 가상환경 안에서 프로그램 실행하기

매번 source activate 명령어를 입력해서 가상환경으로 들어가는 것은 귀찮고 실수의 여지가 있습니다. 따라서 간단하게 아래처럼 스크립트를 만들어서 실행하는 편이 좋습니다.

#!/bin/bash
source activate my_environment
python ~/path/to/target/project/run.py

5.4 가상환경 지우기

위의 절차를 그대로 따라오셨다면 사용하지 않는 webdev 환경이 남아있습니다. 디스크 용량만 차지하니 지우도록 하겠습니다. 가상환경은 만드는 것 만큼이나 지우는 것도 쉽습니다. conda env remove -n ENVIRONMENT 명령으로 가상환경은 바로 지워집니다. conda info --envs로 확인해보세요.

$ conda env remove -n webdev27
$ conda info --envs

6. 마무리

생각보다 글이 길어졌지만 꼭 필요하신 분이 계실 것 같습니다. 많은 분들께 도움이 되면 좋겠네요. 마지막으로 콘다, PIP, Virtualenv의 명령을 비교한 글을 링크합니다. 도움 되시기 바랍니다.

원글

Task Conda package and environment manager command Pip package manager command Virtualenv environment manager command
Install a package conda install $PACKAGE_NAME pip install $PACKAGE_NAME X
Update a package conda update --name $ENVIRONMENT_NAME $PACKAGE_NAME pip install --upgrade $PACKAGE_NAME X
Update package manager conda update conda Linux/OSX: pip install -U pip Win: python -m pip install -U pip X
Uninstall a package conda remove --name $ENVIRONMENT_NAME $PACKAGE_NAME pip uninstall $PACKAGE_NAME X
Create an environment conda create --name $ENVIRONMENT_NAME python X cd $ENV_BASE_DIR; virtualenv $ENVIRONMENT_NAME
Activate an environment source activate $ENVIRONMENT_NAME X source $ENV_BASE_DIR/$ENVIRONMENT_NAME/bin/activate
Deactivate an environment source deactivate X deactivate
Search available packages conda search $SEARCH_TERM pip search $SEARCH_TERM X
Install package from specific source conda install --channel $URL $PACKAGE_NAME pip install --index-url $URL $PACKAGE_NAME X
List installed packages conda list --name $ENVIRONMENT_NAME pip list X
Create requirements file conda list --export pip freeze X
List all environments conda info --envs X Install virtualenv wrapper, then lsvirtualenv
Install other package manager conda install pip pip install conda X
Install Python conda install python=x.x X X
Update Python conda update python * X X