pyenv 설치

Python 의 pyenv 기반 개발환경

데모 환경은 OS X와 리눅스로 한정합니다.

파이썬에는 Python 2와 Python 3이 공존하고, 파이썬 별로 다수의 서브 버전이 존재합니다. 또한, 파이썬 커뮤니티는 엄청난 수의 패키지를 만들고 공유하고 있습니다. 이러한 패키지들은 개별적으로 여러 버전을 갖고 있습니다.

Python의 dependency 관리

Node 모듈으로 만들어지는 Javascript 프로젝트는 package.json으로 Dependency를 관리하고, Ruby 프로젝트는 gemfile실행파일으로 관리한다. 그렇다면 Python은 이 문제를 어떻게 해결할까?

Python은 Virtual Environment 를 지원하는 툴으로 이 문제를 해결한다. 각 프로젝트마다 쓰일 가상 환경(virtual environment)를 생성하여 그 프로젝트에 해당되는 Python을 활성화 한 후에 실행시킨다.

또한 가상 환경 안에 설치된 package들은 python의 freeze 명령어를 통해서 requirements.txt라는 파일로 추출되고, 이것을 git같은 버전 관리 도구로 관리하면, 새로운 개발 환경에서도 쉽게 이를 동기화시킬 수 있다.

pyenv란 무엇인가?

pyenv란 여러 버전의 Python을 쉽게 바꿔서 쓸 수 있게 해주는 도구이다. 예를 들면 3.5.2버전을 쓰다가, 명령어 한 줄로 2.7.12로 버전을 바꾸어서 쓸 수 있게 해준다. 이는 python-virtualenv와 같이 쓰면 더욱 활용도가 높아진다.

단, 윈도우는 지원을 안하고 별도의 [pyenv-win[(https://github.com/pyenv-win/pyenv-win) 을 사용할 수 있다.

여기 다루는 파이썬 가상환경에 대한 툴은 다음과 같이 요약할 수 있습니다.

  1. pyenv
  • 파이썬 버전을 관리하는 툴.
  • 하나의 컴퓨터에 다양한 파이썬 버전을 설치하고 관리.
  • 프로젝트 홈페이지: https://github.com/pyenv/pyenv
  1. pyenv-virtualenv
  • virtualenv은 파이썬 환경을 격리하는 툴.
  • pyenv-virtualenv은 virtualenv의 pyenv 확장 플러그인.
  • 파이썬 버전과 라이브러리의 완전한 격리 환경을 제공.
  1. autoenv
  • autoenv는 디렉터리 이동 시 실행되는 스크립트
  • pyenv-virtualenv 사용 시 불편한 수작업을 자동화.
  • 특정 프로젝트 폴더로 들어가면 .env파일 실행하여 가상환경 활성화.
  1. pip
  • 파이썬 라이브러리를 관리.

pyenv 설치

사전 준비

Python 3.4 이상은 요구한다. pip로 virtualenv 를 설치가 필요하다.

개발환경은

  • Ubuntu 16.04 or later
  • Windows 7 or later
  • macOS 10.12.6 (Sierra) or later (no GPU support)
  • Raspbian 9.0 or later

macOS 설치

필요 조건

pyenv를 OS X(맥)에 설치하기 위해서는 xcode command line tools과 zlib가 먼저 설치되어 있어야 합니다. xcode command line tools과 zlib를 OS X에서 설치하는 명령은 다음과 같습니다. 두 명령을 터미널 상에서 실행합니다.

1
2
$ sudo xcode-select --install
$ brew install homebrew/dupes/zlib

macOS Homebrew 설치

macoS는 homebrew 를 설치해서 사용하는 것을 가정하고 homebrew로 시스템 python 을 설치한다

pyenv를 OS X(맥)에 설치하기 위해서는 xcode command line tools과 zlib가 먼저 설치되어 있어야 합니다. xcode command line tools과 zlib를 OS X에서 설치하는 명령은 다음과 같습니다. 두 명령을 터미널 상에서 실행합니다.

1
2
$ sudo xcode-select --install
$ brew install homebrew/dupes/zlib
1
2
3
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
$ brew update

pyenv 설치: macOS

맥 네이티브로 pyenv를 사용해 Anaconda를 설치하고 텐서플로를 설치해 보자

1
2
brew update
brew install pyenv

pyenv 업그레이드는 다음 명령을 사용합니다.

1
$ brew upgrade pyenv

환경변수

pyenv 경로 설정을 위해 아래를 .bash_profile 에 추가한다.

1
2
3
4
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
# pyenv 초기화
$eval "$(pyenv init -)"

CentOS, Oracle Linux, RHEL 설치

https://github.com/pyenv/pyenv/wiki#suggested-build-environment

사전 준비사항

RedHat 계열 혹은 Debian 계열에서 아래 같은 패키지가 필요할 수 있다.

https://github.com/pyenv/pyenv/wiki#suggested-build-environment

Yum 설치

1
2
$ sudo yum install -y zlib-devel bzip2 bzip2-devel \
readline-devel sqlite sqlite-devel openssl-devel xz xz-devel curl git

우분투 환경에서는 다음과 같은 패키지를 설치합니다.

1
2
3
sudo apt-get update
sudo apt-get install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

pyenv 설치: Linux

리눅스에서 pyenv 설치는 원격 스크립트 pyenv-installer를 사용한다.

pyenv-installer 를 이용하여 pyenv를 설치하면, 다음과 같은 pyenv 플러그인도 설치됩니다.

  • pyenv-doctor
  • pyenv-pip-rehash
  • pyenv-update
  • pyenv-virtualenv
  • pyenv-which-ext

pyenv-installer는 pyenv 설치 스크립트 입니다. rbenv-installer의 스타일을 빌려서 만든 것입니다. pyenv-installer는 리눅스용 쉘 스크립트 파일입니다. pyenv-installer를 이용하여 pyenv를 설치하기 위해서는 curl과 git이 사전에 설치되어 있어야 합니다.

1
curl https://pyenv.run | bash

pyenv.run 이 실행이 안되면 다른 설치 명령은 다음과 같습니다.

1
2
$ curl -L \
https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer \

설치후 아래 같이 경로 추가 메시지가 나온다.

1
2
3
4
5
6
# Load pyenv automatically by adding
# the following to ~/.bashrc:

export PATH="/home/qkboo/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

pyenv를 최신 버전으로 업데이트해야 할 경우 다음 명령을 수행합니다.

1
$ pyenv update

환경변수 적용 및 업데이트

다음 명령을 터머널에서 수행하여 환경변수를 등록합니다.

이 명령으로 아래 코드가 bash를 사용하는 상황을 가정합니다. zsh를 사용하실 때는 “~/.bash_profile“을 “~/.zshrc“로 변경하여 실행해야 합니다.

1
2
3
4
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

pyenv 사용

pyenv는 다음과 형태로 실행됩니다.

pyenv {sub-command} [{parameters}….]
pyenv가 제공하는 서브 명령은 다음과 같습니다.

서브 명령 설명
local 현재 디렉터리에 python 버전 확인 및 python 버전 지정
global 전역으로 설정된 python 버전
shell shell에 파이썬 버전을 지정
install python-build를 이용하여 파이썬 버전을 설치
uninstall 지정한 버전의 파이썬을 삭제
version 현재 활성화된 파이썬 버전 출력
versions pyenv로 설치되어 이용 가능한 버전을 출력
which 활성화된 파이썬 명령의 위치 출력
whence 지정한 명령을 포함하는 모든 파이썬 버전 출력

버전 설치

pyenv로 설치할 수 있는 버전의 목록을 보려면 다음과 같은 명령어를 입력한다.

1
$ pyenv install --list

[list들]
엄청나게 많은 버전들이 있을텐데, 여기서는 현재 최신 버전인 3.5.2버전을 설치하도록 하겠다. (목록에서 위로 올리다 보면 있다)

1
$ pyenv install 3.5.2

이렇게 하면 설치가 완료된다. 설치하는데에 시간이 조금 오래 걸린다. 설치된 목록을 확인하려면 다음과 같은 명령어를 입력한다.

1
2
3
4
$ pyenv versions

* system (set by PYENV_VERSION environment variable)
3.5.2

shell 명령

설치된 버전은 pyenv versions 명령으로 나타나고, 버전 이름 맨 앞의 *표시는 현재 사용하고 있는 Python버전이다. 현재 쉘에서 다른 버전으로 옮기려면 shell 명령어를 입력한다.

1
$ pyenv shell 3.5.2

Uninstall

This is handy because removing these versions is trivial:

1
$ rm -rf ~/.pyenv/versions/2.7.15

Of course pyenv also provides a command to uninstall a particular Python version:

1
$ pyenv uninstall 2.7.15

Global & Local

시스템 수준의 버전 지정은 global 명령과 local 명령으로 지정할 수 있다.

global 글로벌 설정

pyenv를 시스템 수준의 python 버전을 설정해서 시스템의 기본 파이썬 버전으로 지정할 때 유용하다.

다음은 컴퓨터의 글로벌 파이썬 버전을 파이썬 2.7.12에서 새로 설치한 파이썬 3.5.3으로 변경하는 예입니다. 아래 명령을 수행한 후, python을 실행하면 Python 3.5.3 버전이 실행됩니다

1
2
3
$ pyenv versions
* system
3.5.3 (set by /Users/qkboo/.pyenv/version)
1
2
3
4
5
6
7
8
9
$ python --version    ## 현재 파이썬 버전
Python 2.7.12
$ pyenv global 3.5.3 ## 글로벌 파이썬 설정 변경
$ python --version ## 현재 파이썬 버전
Python 3.5.3
$ pyenv versions ## pyenv 활성 버전 확인
system
* 3.5.3 (set by /Users/qkboo/.pyenv/version)
$

global 명령을 내리면 ~/.pyenv/version 파일을 해당 버전으로 지정한다

local 로컬 설정

특정 디렉터리에 활성화되는 파이썬 버전을 지정할 수 있습니다. 그리고 로컬 디렉토리 이외에서는 global 설정이 적용됩니다.

다음은 pyenv global과 pyenv local을 사용하는 방법의 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ pyenv versions           ## global 설정 3.5.3
system
2.7.13
* 3.5.3 (set by /home/opc/.pyenv/version)

$ python -V ## Global 파이썬 버전
Python 3.5.3
$ mkdir py2.7
$ cd py2.7/
$ pyenv local 2.7.13 ## local 설정 2.7.13
[py2.7]$ python -V
Python 2.7.13
[py2.7]$ ls -al
total 12
drwxrwxr-x 2 opc opc 4096 Sep 8 01:47 .
drwx------. 10 opc 500 4096 Sep 8 01:47 ..
-rw-rw-r-- 1 opc opc 7 Sep 8 01:47 .python-version
[py2.7]$ cat .python-version ## local 설정 파일
2.7.13
[py2.7]$ cd .. ## global 설정 3.5.3
$ python -V
Python 3.5.3
[opc@b4b8b6 ~]$

“pyenv local“를 실행하면 해당 디렉터리에 .python-version 파일이 생기고 이 파일에 활성화될 파이썬 버전이 기록됩니다.

Test suite

Pro Tip: A great way to get peace of mind that the version of Python you just installed is working properly is to run the built-in test suite:

1
2
$ pyenv global 3.8-dev
$ python -m test

This will kick off lots of internal Python tests that will verify your installation. You can just kick back and watch the tests pass.

Using your environment in IDEs

If you are not as sehell person, you can also use pyenv with your favourite IDE. Many editors and IDEs are aware of pyenv environments and will detect them for you. Then you will be able to select the environment for your current workspace from a dropdown menu.

참고

Jupyterlab 에서 password 생성해 systemd 서비스 이용

Jupyter Lab - systemd 운영

jupyterlab 을 Itel 기반의 Ubuntu 시스템에 설치하고 시스템 서비스로 등록하는 과정.

  1. Ubuntu 18.04
  2. node.js
  3. Anaconda 2020

Restart your shell so the path changes take effect. You can now begin using pyenv.

1
exec "$SHELL"

Anaconda 배포본 설치 (Ubuntu)

우분투용 다운로드

https://www.anaconda.com/products/individual#linux

다움로드안 쉘 스크립트를 시작한다.

1
bash ~/Downloads/Anaconda3-2020.02-Linux-x86_64.sh

To control whether or not each shell session has the base environment activated or not, run conda config –set auto_activate_base False or True. To run conda from anywhere without having the base environment activated by default, use conda config –set auto_activate_base False. This only works if you have run conda init first.

Anaconda 를 설치하면 대부분의 패키지가 내장되어 있다.

설치후 최신 conda 환경 base를 갱신해 준다.

1
conda update -n base -c defaults conda

nvm으로 Node.js 설치

nvm 설치

1
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash

스크립트로 설치를 완료하면 쉘 시작시 nvm 환경을 구성하기 위해서아래 스크립이 자동으로 현재 쉘 스크립트 파일 끝에 추가된다.

만약 아래 스크립이 추가 안되면 아래 스크립트를 (~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.bashrc).)에 추가한다.

1
2
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

node.js 설치

1
2
3
4
5
6
~$ nvm ls-remote
v14.0.0
v14.1.0
v14.14.0
v14.15.0 (LTS: Fermium)
v14.15.1 (Latest LTS: Fermium)

lts 최신 버전 14.0을 설치한다.

1
2
3
4
5
6
7
8
~$ nvm install --lts 14.15.1
Downloading and installing node v14.15.1...
Downloading https://nodejs.org/dist/v14.15.1/node-v14.15.1-linux-x64.tar.xz...
######################################################################### 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v14.15.1 (npm v6.14.8)
Creating default alias: default -> lts/* (-> v14.15.1)

node 버전을 확인

1
2
~$ node --version
v14.15.1

Conda 에서 jupyterlab 설치

Anaconda 나 Miniconda 를 설치하고 가상환경을 하나 생성한다.

1
2
3
4
$ conda create -n tf2 jupyterlab numpy scipy matplotlib tensorflow

$ conda activate tf2
(tf2) ~$

JupyterLab 실행

가상환경에서 jupyterlab 을 외부에서 접속 가능하도록 실행하자.

1
(base) $ jupyter-lab --no-browser --ip=* --port=8888 ~/Jupyter-Notebook/

LabConfig 디렉토리

1
2
3
4
5
6
7
8
9
10
11
12
13
$ jupyter --paths
config:
/home/qkboo/.jupyter
/home/qkboo/anaconda3/envs/py3/etc/jupyter
/usr/local/etc/jupyter
/etc/jupyter
data:
/home/qkboo/.local/share/jupyter
/home/qkboo/anaconda3/envs/py3/share/jupyter
/usr/local/share/jupyter
/usr/share/jupyter
runtime:
/home/qkboo/.local/share/jupyter/runtime

JupyterLab 환경 설정

jupyter 의 config 파일을 통해서 인증과 구성을 하자.

  • jupyterlab 3.x 버전: jupyter_server_config.py
  • jupyterlab 2.x 버전: jupyter_notebook_config.py

Jupyter Lab 에서 설정 파일을 생성한다. 다음 명령으로 각각 $HOME/.jupyter/ 위치에 jupyter_server_config.py 파일이 생성된다.

1
2
(tf2)$ jupyter lab --generate-config
Writing default config to: /home/qkboo/.jupyter/jupyter_server_config.py

패스워드 사용

jupyter_notebook_config.py 설정 파일에 비밀번호를 추가하려면 비밀번호를 생성해야 한다. 아래 명령으로 생성한다.

1
2
3
4
(tf2)$ jupyter lab password
Enter password:
Verify password:
[NotebookPasswordApp] Wrote hashed password to $HOME\.jupyter\jupyter_server_config.json

jupyter_server_config.json 파일로 암호가 생성된다. 생성한 암호를 jupyter_server_config.py 파일의 c.ServerApp.password 항목에 입력해 준다

1
2
3
4
5
[jupyter_server_config.py]

c.ServerApp.password = 'sha1:*********' # 외부 접속시 사용할 비밀번호
c.ServerApp.ip = '*' # 어디서든 접속 가능
c.ServerApp.port = 8888 # 접속에 사용할 포트

Jupyter Lab 3.x 버전

1
2
3
4
5
6
7
8
9
c.ServerApp.base_url = '/notebook'
c.ServerApp.enable_mathjax = True
c.ServerApp.password = ''
c.ServerApp.ip = '*'
c.ServerApp.port = 8888
c.ServerApp.port_retries = 10
c.ServerApp.open_browser = False

c.ServerApp.tornado_settings = {"websocket_max_message_size": 400 * 1024 * 1024}

Jupyter Notebook, Jupyterlab 2.x 버전:

1
2
3
4
5
6
7
8
9
c.NotebookApp.base_url = '/notebook'
c.NotebookApp.enable_mathjax = True
c.NotebookApp.password = ''
c.NotebookApp.ip = '*'
c.NotebookApp.port = 8888
c.NotebookApp.port_retries = 10
c.NotebookApp.open_browser = False

c.NotebookApp.tornado_settings = {"websocket_max_message_size": 400 * 1024 * 1024}

systemd 구성

nodejs, jupyter lab 을 시스템 시작 서비스로 등록한다. node.js 경로, jupyterlab 을 위한 시작 환경이 필요하다.

systemd의 unit 위치는 OS 마다 조금 다른 것 같다.

여기서는 /etc/systemd/system 밑에 jupyter.service 라는 유닛 파일에 아래 같이 파이썬 환경을 포함해 작성한다.

가상환경을 사용하고 있으므로 systemd unit의 ExecStart 의 python도 가상환경 위치로 지정해 주어야 한다.

유닛 파일: /etc/systemd/system/jupyter.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Unit]
Description=My Jupyter-Notebook

[Service]
Type=simple
PIDFile=/run/jupyter-notebook.pid
# nodejs path
Environment="PATH=/home/qkboo/.nvm/versions/node/v12.18.0/bin/:/usr/local/bin:/ usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin"

# anaconda: tf2
ExecStart=/home/qkboo/anaconda3/envs/tf2/bin/jupyter-lab --config /home/qkboo/Home/mybook_config.py
User=qkboo
Group=qkboo
WorkingDirectory=/home/qkboo/Home/Jupyter-Notebook/
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

유닛 파일 등록과 시작

jupyter.service 파일을 등록한다.

1
$ sudo systemctl enable jupyter

등록한 유닛 파일을 확인해 보자.

1
2
3
$ sudo systemctl list-unit-files | grep jupyter
jupyter_book.service disabled enabled
jupyter.service enabled enabled

그리고 데몬을 리로드 한다.

1
2
$ sudo systemctl daemon-reload
$ sudo systemctl start jupyter

실행한 서비스를 종료하려면

1
$ sudo systemctl stop jupyter

실행 상태를 확인한다.

1
$ sudo systemctl status jupyter

유닛 파일 등록 해지

1
2
$ sudo systemctl disable jupyter
Removed /etc/systemd/system/multi-user.target.wants/jupyter.service.

서비스 상태

해당 서비스 상태 확인

1
$ sudo systemctl status jupyter

구동에 실패한 서비스 보기

1
$ sudo systemctl list-units --state=failed

enabled 상태인 서비스 목록

1
$ sudo systemctl list-units --state=enabled