pipenv 소개

Pipenv 뭐하는 녀석인가?

  • python.org 에서 공식적으로 추천하는 패키지 관리툴
  • 세계에서 제일가는 패키징툴을 만드는게 목표라고 한다…
  • virtualenv 환경을 자동으로 만들어 준다.
  • Pipfile 에 패키지를 더하거나 빼거나 하면 됨.
  • Pipfile이라는 녀석이 Pipfile.lock 이라는 겁나 중요한 파일을 생성하는데, 결정론적 빌드(deterministic builds)에 쓰인다.
  • 이거 만든사람은… requests 만든사람이다. requests를 만들었을 때처럼 인터페이스가 깔끔하다.
  • 지 블로그에는 주말에 만들었다고 올려놨다… https://www.kennethreitz.org/essays/announcing-pipenv
  • 주말에 만들었다고는 하지만, 케네스의 깃헙을 보면 비슷한 시도들을 많이 한것으로 보인다.
  • 즉, 능력자의 삽질의 결과물인 것이다.

Pipenv가 해결하려고 하는 문제들

  • pip 와 virtualenv 를 분리된 상태로 사용하는 것이 아니라, pipenv 하나만 사용하기
  • requirement.txt 파일의 관리를 별도의 코드가 아닌 Pipfile, Pipfile.lock 으로 할 수 있도록 해주는 것
  • 해쉬의 자동생성(보안관련)
  • pipenv graph 명령어로 의존성 그래프를 직관적으로 볼 수 있음
  • .env 파일들을 사용한 스트림라인 개발 워크플로우

기능들

  • 딱 필요한 것만 정의 하면서도, 레알 결정론적 빌드가 가능하다.
    • 결정론적 빌드라는게 뭐냐면 그냥 파일에 정해진대로 빌드를 할 수 있다는 말이고,
      빌드가 상황과 환경에 좌지우지 되지 않는 다는 것을 말한다.
  • 락이 걸린 의존성에 대한 해쉬 파일들을 만들어준다. (Pipenv.lock 파일)
  • pyenv가 설치되어 있으면, 파이썬도 자동으로 설치해줌
  • Pipfile 을 사용해서 자동으로 프로젝트 홈을 찾아줌
  • Pipfile이 없으면 자동으로 만들어줌
  • 자동으로 virtualenv 환경을 만들어줌
  • Pipfile 에서 추가/삭제하면 해당 패키지도 추가/삭제 됨. (오 좀 짱인듯)
  • .env 파일이 있으면 자동으로 인식 (환경변수를 자동으로 인식할 수 있음)
  • 주된 커맨드는 install, uninstall, lock 이고, 요넘들은 Pipfile.lock 이라는 파일을 만들어냄.

기본 컨셉

  • virtualenv 환경(이 없으면) 자동 생성
  • install 커맨드에 파라메터를 안넣으면 정의 되어 있는 의존성 몽땅 설치
  • pipenv --three 실행하면 python3 환경을 뚝딱 만들어줌
  • pipenv --two 실행하면 python2 환경을 만들어줌
  • 이러나 저러나 virtualenv 는 기본이자 기본이다.
  • 한마디로 줄이면 자동생성을 수동으로(커맨드는 날려야되니) 편리하게 해준다 정도

다른 명령어들

  • shell : virtualenv 환경 활성화
  • run : virtualenv 의 run 커맨드랑 동일
  • check : 현재의 환경이 PEP508 의 스펙 내용을 만족하는지 확인
  • graph : 의존성 트리를 보여줌

Shell Completion (뭐라해야될지 모르겠지만, 쉘에 넣어두면 pipenv가 활성화됨)

  • eval “$(pipenv –completion)”
  • fish shell 이 젤좋은  쉘이라고 쓰라고 약을 팔고 있으나 안쓸꺼임 ㅎㅎ
#### 프로젝트 위치 찾기
$ pipenv --where
#### virtualenv 위치 찾기
$ pipenv --venv
#### python 인터프리터 위치 찾기
$ pipenv --py

사용법

$ pipenv
Usage: pipenv [OPTIONS] COMMAND [ARGS]...
Options:
  --update         Update Pipenv & pip to latest.
  --where          Output project home information.
  --venv           Output virtualenv information.
  --py             Output Python interpreter information.
  --envs           Output Environment Variable options.
  --rm             Remove the virtualenv.
  --bare           Minimal output.
  --completion     Output completion (to be eval'd).
  --man            Display manpage.
  --three / --two  Use Python 3/2 when creating virtualenv.
  --python TEXT    Specify which version of Python virtualenv should use.
  --site-packages  Enable site-packages for the virtualenv.
  --jumbotron      An easter egg, effectively.
  --version        Show the version and exit.
  -h, --help       Show this message and exit.
Usage Examples:
   Create a new project using Python 3.6, specifically:
   $ pipenv --python 3.6
   Install all dependencies for a project (including dev):
   $ pipenv install --dev
   Create a lockfile containing pre-releases:
   $ pipenv lock --pre
   Show a graph of your installed dependencies:
   $ pipenv graph
   Check your installed dependencies for security vulnerabilities:
   $ pipenv check
   Install a local setup.py into your virtual environment/Pipfile:
   $ pipenv install -e .
Commands:
  check      Checks for security vulnerabilities and...
  graph      Displays currently–installed dependency graph...
  install    Installs provided packages and adds them to...
  lock       Generates Pipfile.lock.
  open       View a given module in your editor.
  run        Spawns a command installed into the...
  shell      Spawns a shell within the virtualenv.
  uninstall  Un-installs a provided package and removes it...
  update     Uninstalls all packages, and re-installs...

설치하기

$ pip install pipenv

의존성 패키지 설치

### 1개 설치
$ pipenv install pytest
$ pipenv install

개발환경일때의 의존성 패키지 설치

### 1개 설치
$ pipenv install pytest --dev
### 전부 설치
$ pipenv install --dev

파이썬 shell 사용하기

$ pipenv shell

프로젝트에 적용 해보기

django로 되어 있는  프로젝트에 적용해 보자

### 프로젝트 루트 디렉토리로 이동
$cd exid
### 아무것도 없지만, 몽땅 설치를 실행한다!
$ ppipenv install
Creating a virtualenv for this project…
⠋Using base prefix '/pyenv/versions/3.4.3'
New python executable in /
Installing setuptools, pip, wheel...done.
Virtualenv location: /
Requirements.txt found, instead of Pipfile! Converting…
Warning: Your Pipfile now contains pinned versions, if your requirements.txt did.
We recommend updating your Pipfile to specify the "*" version, instead.
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (489182)!
Installing dependencies from Pipfile.lock (489182)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 31/31 00:00:25
To activate this project's virtualenv, run the following:
 $ pipenv shell
Spawning environment shell (/usr/local/bin/zsh). Use 'exit' to leave.
source /activate
# Load pyenv-virtualenv automatically by adding
# the following to ~/.zshrc:
eval "$(pyenv virtualenv-init -)"
  • pipenv 가 실행된 다음의 로그를 읽어보자
  • virtualenv 환경이 없으니 pipenv가 pyenv의 파이썬 버전을 읽어서 virtualenv를 하나 만들어준다. virtualenv 이름이 마음에 안들긴 하는데, 딱히 잘 안쓰니 상관없나 싶기도 함
  • 놀랍게도 requirements.txt 파일이 있는 것을 찾아냈다.
  • Pipfile.lock 도 없어서 만들어주고, requirements.txt에 설정된 패키지들을 몽땅 설치하고, Pipfile.lock 도 업데이트를 한다.

pipenv 로 만든 virtualenv 환경 활성화 하기

#### pipenv shell 을 실행하면 virtualenv 환경으로 만들어줌
$ pipenv shell
➜  exid git:() ✗ source /~/exid-NTYXrrm5/bin/activate
(exid-NTYXrrm5) ➜  exid git: ✗
  • 역시나 랜덤하게 만들어지는 virtualenv 이름은 마음에 안든다.

pipenv run

virtualenv를 활성화 하지 않고 해당 환경에서 파이썬 파일을 실행하는 방법은 pipenv run 커맨드를 이용하는 것이다.

$ pipenv run python my_project.py

자주 사용하게될 녀석이니 앨리어스로 등록해두자. vim 사용자라면, .vimrc 에 추가하면 된다.

### 별칭은 알아서 잘 만들자
alias pipython="pipenv run python"
alias prp="pipenv run python"

Pipfile과 Pipfile.lock

Pipfile

  • 위에서 pipenv install 명령어 한방으로 생성한 파일이다.
  • dev 는 아직 없으나 나중에 필요하면 채워놓자.
[[source]]
name = "pypi"
verify_ssl = true
[packages]
amqp = "==2.1.4"
billiard = "==3.5.0.2"
celery = "==4.0.2"
"contextlib2" = "==0.5.4"
Django = "==1.8.5"
django-braces = "==1.9.0"
django-crispy-forms = "==1.6.1"
django-extensions = "==1.7.4"
django-floppyforms = "==1.7.0"
djangorestframework = "==3.3.1"
elasticsearch = "==2.4.0"
kombu = "==4.0.2"
mysqlclient = "==1.3.7"
olefile = "==0.44"
Pillow = "==4.0.0"
pycrypto = "==2.6.1"
pytz = "==2016.10"
raven = "==6.2.1"
redis = "==2.10.5"
redis-py-cluster = "==1.1.0"
requests = "==2.9.1"
serpy = "==0.1.0"
simplejson = "==3.10.0"
"urllib3" = "==1.19.1"
uWSGI = "==2.0.15"
vine = "==1.1.3"
xlwt = "==1.2.0"
mongoengine = "==0.13.0"
django-widget-tweaks = "==1.4.1"
[dev-packages]

Pipfile.lock

{
    "_meta": {
        "hash": {
            "sha256": "e0bb552e2ab575fa5141985b686ac5e49da21bdda3444cfd1273a5927f489182"
        },
        "host-environment-markers": {
            "implementation_name": "cpython",
            "implementation_version": "3.4.3",
            "os_name": "posix",
            "platform_machine": "x86_64",
            "platform_python_implementation": "CPython",
            "platform_release": "17.3.0",
            "platform_system": "Darwin",
            "platform_version": "Darwin Kernel Version 17.3.0: Thu Nov  9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64",
            "python_full_version": "3.4.3",
            "python_version": "3.4",
            "sys_platform": "darwin"
        },
        "pipfile-spec": 6,
        "requires": {},
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.python.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "amqp": {
            "hashes": [
                "sha256:5e0871a93433f941e444c2b859da095f05034d2ac1b7c084529cfd0b6f8eef18",
                "sha256:1378cc14afeb6c2850404f322d03dec0082d11d04bdcb0360e1b10d4e6e77ef9"
            ],
            "version": "==2.1.4"
        },
        "billiard": {
            "hashes": [
                "sha256:82478ebdd3cd4d357613cb4735eb828014364c5e02d3bba96ea6c1565a2c0172",
                "sha256:a93c90d59fca62ad63f92b3d2bf1d752c154dde90a3100dba4c8e439386e534c",
                "sha256:d8df4b276b11b3e2fe25652e411487bda6e5bac4f8fd236a278a2bfe300f7c43",
                "sha256:e740e352bbf7b6c8cc92a2596cc2da2bfb4ab1009aeb68bf844456af4e924278",
                "sha256:52c2e01c95c6edae9ca1f48d83503e6ceeafbf28c19929a1e917fe951a83adb1",
                "sha256:03f669755f1d6b7dbe528fe615a3164b0d8efca095382c514dd7026dfb79a9c6",
                "sha256:3eb01a8fe44116aa6d63d2010515ef1526e40caee5f766f75b2d28393332dcaa"
            ],
            "version": "==3.5.0.2"
        },
          ... 중략
    },
    "develop": {}
}
  • Pipfile.lock 은 의존성 패키지의 검증을 담당한다.
  • 의존성이 있는 패키지가 의존하고 있는 패키지들도 함께 검사를 해주게 되므로 Pipfile.lock 을 잘 사용해서 안심하고 쓸 수 있게 되는 것이다.

dev 에 패키지를 추가해보자

$ pipenv install mock --dev
Installing mock…
Collecting mock
  Downloading mock-2.0.0-py2.py3-none-any.whl (56kB)
Collecting pbr>=0.11 (from mock)
  Downloading pbr-3.1.1-py2.py3-none-any.whl (99kB)
Requirement already satisfied: six>=1.9 in //lib/python3.4/site-packages (from mock)
Installing collected packages: pbr, mock
Successfully installed mock-2.0.0 pbr-3.1.1
Adding mock to Pipfile's [dev-packages]…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (bd3f8c)!
  • Pipfile 에 추가하고
  • 각 환경에서의 의존성이 걸리는 부분을 확인 한다음
  • Pipfile.lock 을 업데이트한다.

Pipfile [dev-packages] 부분

[dev-packages]
mock = "*"

Pipfile.lock  “develop” 부분

"develop": {
    "mock": {
        "hashes": [
            "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1",
            "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"
        ],
        "version": "==2.0.0"
    },
    "pbr": {
        "hashes": [
            "sha256:60c25b7dfd054ef9bb0ae327af949dd4676aa09ac3a9471cdc871d8a9213f9ac",
            "sha256:05f61c71aaefc02d8e37c0a3eeb9815ff526ea28b3b76324769e6158d7f95be1"
        ],
        "version": "==3.1.1"
    },
    "six": {
        "hashes": [
            "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
            "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
        ],
        "version": "==1.11.0"
    }
}

개발환경과 운영환경에서는 어떻게 적용할까?

개발환경

–dev 를 붙이면 [packages] 와 [dev-packages] 둘다 설치하므로 아래의 명령어를 그냥 날리면 된다.

pipenv install --dev

샌박, 베타, 실서버

운영환경에서는 [packages] 에 있는 것만 설치하면 되니 –dev 를 빼고 실행하면 되겠다.

$ pipenv install

참고

깃헙 : https://github.com/pypa/pipenv

매뉴얼 : https://media.readthedocs.org/pdf/pipenv/latest/pipenv.pdf

케네스 아저씨 블로그 : https://www.kennethreitz.org/essays/announcing-pipenv