魂の生命の領域

AWS とか Python とか本読んだ感想とか哲学とか書きます

Pipenv 、すこだw(キモオタ)

概要

2020-09-10 追記:今読むとカスみたいな内容なのでその内書き直します。

導入

プログラミングをやり始めたころは、とりあえず言語も外部ライブラリも最新版をグローバルにインストールして使ったりしてましたが、プロジェクトによって言語や外部ライブラリのラインナップやバージョンが違うことは当然のようにあります。

また、プロジェクト、具体的には git のリポジトリごとに必要な言語のバージョンやライブラリを指定して開発する人みんなが同じ道具で開発できるようにする必要もあります。

Pipenv の話なので Python に限って話をしますが、今までは

$ pip install hogehoge

のように外部ライブラリをインストールして最後に

$ pip freeze > requirements.txt

を実行してインストールした外部ライブラリを書き出し、逆に使う人は

$ pip install -r requirements.txt

を実行して必要な外部ライブラリを一括でインストール、みたいなことをしていました。

このとき、グローバルになんでもかんでも入れていると pip freeze したときに関係ないライブラリが入ったりして怒られたりします。

というかそもそもライブラリ以前に Python のバージョンが違う場合もあるので、そこも色々してやらないといけません(適当)。 Python 3.3 か 3.4 以降からは標準ライブラリに venv というものがあるので一時期使ってたことありました。

git のリポジトリ、つまりローカルで見た時はディレクトリの単位で Python のバージョンやライブラリを管理できればいいわけです。そのためのハイパー便利なツールが Pipenv というやつです。

ちなみに今までは Linux で開発するときは(anyenv を入れた上で) pyenv と virtualenv で仮想環境を管理していたのですが、Windows では使えないので一旦 git push したあとまっさらな Linux 側で git clone して動かして必要なものをその都度入れて pip freeze してました。アホですね。

Pipenv の話

長々と書こうとするとアホがバレるので箇条書きします。

  • Python のパッケージ管理ツールと仮想環境を合わせたようなやつ
  • いちいち pip freeze > requirements.txt しなくてよくなる
  • Pipfile.lock によって pip freeze のやつよりも厳格にバージョンや依存関係の管理ができる
  • 各種コマンド実行時の標準出力がカラフルで見やすいし蛇のアイコンが可愛い

早速使い方を見ていきます。

手順

ひとまず Pipenv をインストールします。

$ pip install pipenv

ちなみに pipenv --help したらもう必要な情報は全部分かりやすく出てくるのでここでこの記事の存在意義はなくなります。

作業ディレクトリを作ってそこに入ります。

$ mkdir pipenv_tutorial
$ cd pipenv_tutorial

Pipenv で Python のバージョンを指定し仮想環境を作成します。

$ pipenv --python 3.6

pipenv --three とか pipenv --two とかも出来るみたいですが、折角上のように細かく指定できるのでこっちを使うことあるのかな?という感じです。

すると Pipfile という名前のファイルが生成されます。

中身はこんなのです。

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]

[requires]
python_version = "3.6"

このファイルの [packages] 以下の行にこの仮想環境にインストールされたライブラリが列挙されていきます。

実際に仮想環境にライブラリをインストールしてみます。

$ pipenv install boto3

AWS SDK for Python であるところの皆大好き boto3 を入れてみました。 もう一度 Pipfile を見ると確かに boto3 が追記されています。

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
boto3 = "*"

[requires]
python_version = "3.6"

boto3 = "*" の右辺には具体的なバージョンが書かれます。今はバージョンを指定していないのでワイルドカードになっていますね。

そして Pipfile.lock というファイルも自動で生成されます。 中身を見るとやたら行数が多くて面食らってしまいますが、これによってライブラリのバージョンや依存関係をガッチリ定義してくれています。

pipenv install を叩いたときに、 Pipfile.lock が存在したときは Pipfile.lock を元にライブラリをインストールしてくれます。存在しないときは Pipfile を元にライブラリをインストールします。

なので、上の例で Pipfile 内では boto3 のバージョンは boto3 = "*" と書いているので、Pipfile.lock が存在しない時はその時点での最新バージョンがインストールされます。

一方で、 Pipfile.lock が存在するときは Pipfile.lock に書かれたバージョンの boto3 (つまり Pipfile.lock 生成時にバージョン指定せず boto3 をインストールした結果実際にインストールされたバージョンの boto3 )がインストールされます。

{
    "_meta": {
        "hash": {
            "sha256": "54ff8dee333d9809ab3b92890bd62c4ba07ee9032dae28cf68db4fcd2000df60"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.6"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "boto3": {
            "hashes": [
                "sha256:8d934fcfca83c6ce40d53043cc94b1de6eef1d2dbe2a196343941587717ad1b7",
                "sha256:e221f6867282266e06aec2213f0ea5fdbd4eb3facbca4fcbf96886073350bc5e"
            ],
            "index": "pypi",
            "version": "==1.9.210"
        },
        "botocore": {
            "hashes": [
                "sha256:0db52327f8d2891cca4c86dfc5cb3b4821d37b84c34804c26b82e775668490f5",
                "sha256:7983b7624b3f71648a7101fbcb437e3d599b4f79b754e89220e574482a2f8298"
            ],
            "version": "==1.12.210"
        },
        "docutils": {
            "hashes": [
                "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0",
                "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827",
                "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99"
            ],
            "version": "==0.15.2"
        },
        "jmespath": {
            "hashes": [
                "sha256:3720a4b1bd659dd2eecad0666459b9788813e032b83e7ba58578e48254e0a0e6",
                "sha256:bde2aef6f44302dfb30320115b17d030798de8c4110e28d5cf6cf91a7a31074c"
            ],
            "version": "==0.9.4"
        },
        "python-dateutil": {
            "hashes": [
                "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
                "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
            ],
            "markers": "python_version >= '2.7'",
            "version": "==2.8.0"
        },
        "s3transfer": {
            "hashes": [
                "sha256:6efc926738a3cd576c2a79725fed9afde92378aa5c6a957e3af010cb019fac9d",
                "sha256:b780f2411b824cb541dbcd2c713d0cb61c7d1bcadae204cdddda2b35cef493ba"
            ],
            "version": "==0.2.1"
        },
        "six": {
            "hashes": [
                "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
                "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
            ],
            "version": "==1.12.0"
        },
        "urllib3": {
            "hashes": [
                "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
                "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
            ],
            "markers": "python_version >= '3.4'",
            "version": "==1.25.3"
        }
    },
    "develop": {}
}

バージョンを規定するファイルが自動で生成/更新されることからも分かるように、 git でバージョン管理している場合はめちゃくちゃ便利です。 自分で明示的に pip freeze しなくて良いのです。

さて、何かしらコードを書いたのち、作成した仮想環境内で Python を実行します。

$ pipenv run hoge.py

私は仮想環境を有効化する方が分かりやすい気がするので以下のコマンドを実行しています。

$ pipenv shell

これをやれば今まで通り python hoge.py を叩いても仮想環境で実行してくれます。

仮想環境を抜けたいときはこれです。

$ exit

今度は Pipfile と Pipfile.lock があるリポジトリを git clone したときを考えます。

基本的にはこのコマンドを実行するだけです。

$ pipenv install

そうすると Pipfile の [packages] 以下に書かれたライブラリが Pipfile.lock でガッチリ規定されたバージョン通りにインストールされます。

後は pipenv runスクリプトを実行するなり pipenv shell でその環境に入ってしまうなりすればそれで OK な訳です。

ちなみに Pipfile には [packages] の上に [dev-packages] という項目もあります。 開発環境と本番環境ではライブラリを分けたい際には

$ pipenv install --dev

としてやれば [dev-packages] に書かれたライブラリのみをインストールすることができます。

まとめ的なもの

  • Pipenv 超便利!
  • 基本的にはここで書いた内容で事足りると思っていますが、まだまだ面白そうな機能はあるので以下のドキュメント?も読んでみたら楽しいかもしれません