• 4/30 公開
  • 5/1 増補改訂: 大幅加筆しました。

この記事では、2018年以降に実現可能になったモダンなPythonプロジェクトのはじめかたを整理して紹介します。

PythonにもPipenvという公式推奨の高機能なパッケージマネージャーが登場し、さらに2018年に入ってからの機能向上で、npmやyarnのような開発体験が得られるようになってきました。

私はここしばらくはフロントエンドやNode.jsに携わっていて、npmやyarnに慣れきっていたせいか、pipenv導入以前はvirtualenvやpipを組み合わせた開発が面倒で仕方なかったですが、Pipenv導入によって一変しました。

これからはPythonのプロジェクトがよりクリーンかつ簡単にはじめられるようになり、開発体験も向上するでしょう。

それでは、まずはPythonのインストールからです。

Pythonのインストール

Pipenvではpyenvを推奨しています。PipenvとPyenvを組み合わせると、プロジェクトが指定するバージョンのPythonを自動でインストールできます。

ただしPyenvを使わなくても特に問題はありません。Pyenvが不要な人は別の方法でPythonをインストールしてもかまいません。

参考: pyenvが必要かどうかフローチャート

Pyenvのインストール

brew install pyenv

.zshrc.bashrcにpyenvの設定を追加します。

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

PyenvでのPythonのインストール

Python 3.6.5をインストールして標準にする例です。

pyenv install 3.6.5
pyenv global 3.6.5

これで任意のバージョンのPythonをいつでも使えるようになりました。

さて、ここからが本題です。

Pipenv: プロジェクトやパッケージの管理

pipenvの登場で、PythonでもNode.jsのyarnやnpmのように、プロジェクトを管理できるようになりました。

もはやパッケージ管理にpip freezerequirements.txtを使う必要はありません。面倒だったvirtualenvも意識しないで済むようになりました。

Pipenvインストール

brew install pipenv

pip経由でもインストールできます。

pip install pipenv

pipenv install: パッケージのインストール

プロジェクトのディレクトリを新規作成して移動します。

mkdir my_project && cd my_project

アプリで必要なパッケージをインストールします。

例:requestsを使う場合

pipenv install requests

これによって、プロジェクトを管理するPipfilePipfile.lockがディレクトリ直下に作られて、パッケージの依存関係などが管理されます。

パッケージのバージョンを指定する

パッケージのバージョンを指定してインストールできます。

pipenv install keras==2.1.6

Pythonのバージョン指定する

プロジェクトで使用するPython本体のバージョンを指定することもできます。

pipenv --python 3.6.5 (ex. 3, 3.6, 3.6.5)

Pyenvを使っている場合は、ここで指定したPythonを自動インストールするようにできます。

Pipfile scriptsによる操作の抽象化

npmでは、npm run コマンド名によって、どのプロジェクトでも一様に、アプリの起動/静的解析/テスト/コードフォーマットなどを実行できます。

Pythonでも、Pipenvのscripts機能によって、これが自然にできるようになりました。

アプリの起動/起動スクリプト:

プロジェクトごとにアプリの起動方法は異なると思いますが、毎回打ち込むのは面倒ですよね。

というわけで、どのプロジェクトでもpipenv run start一発でアプリを起動できるようにします。

そのためには、プロジェクトのディレクトリ直下のPipfile[scripts]を追加します。

[scripts]を追加したら、その下に実行したいコマンドを定義します。

pipenv run startapp.pyを起動する例です。

[scripts]
start = "python app.py"

package.jsonscriptsにコマンドを書くのと一緒です。

アプリの起動

それでは、実際にアプリを起動してみます。

pipenv run start

どのプロジェクトでもこのコマンドだけで、アプリを起動できるので楽ですね。

Flake8: 静的解析

静的解析もコマンド化します。

ここでは、pyflakeでPEP8とPyFlakeに従って静的解析します。

同じようなにPipfileにコマンドを追加します。

インストール

開発環境だけで使うパッケージをインストールする時は--devオプションをつけます。

pipenv install --dev flake8

Pipfile編集

先ほどと同様にPipfileを編集します。lintコマンドで静的解析できるようにします。

[scripts]
 :
lint = "flake8 ."
 :

静的解析実行

静的解析を実行します。lintコマンドで静的解析の実行を抽象化することができました。

pipenv run lint

Autopep8: コードフォーマット

コードフォーマットもscripts化しておきます。autopep8を使ってPEP8に従ってコードを自動修正します。

インストール

pipenv install --dev autopep8

Pipfile編集

ディレクトリ配下のコードを再帰的に修正する例です。

[scripts]
 :
fix = "autopep8 -ivr ."
 :

オプションのiは上書き、vはデバッグ、rは再帰実行です。

コードフォーマット実行

fixコマンドでコードが自動修正されるようになりました。

pipenv run fix

コードフォーマットのコマンドやオプションを覚える必要もありません。

作成したプロジェクトを別の環境で使う

1コマンドで同じプロジェクトを再現できます。

Production環境の場合

pipenv install

開発用以外の依存パッケージが自動でインストールされます。

Pyenvを使っていて、Pipfileに指定されたバージョンのPythonがインストールされていない場合は、Pythonも同時にインストールできます。GitHubに公開する場合にも便利ですね。

開発環境の場合

pipenv install --dev

Production用のパッケージに加えて、開発用のパッケージもインストールされます。

パッケージのセキュリティ脆弱性検出

インストールしたパッケージにセキュリティ脆弱性がないかチェックしてくれます。

pipenv check

結果

Checking PEP 508 requirements…
Passed!
Checking installed package safety…
All good!

セキュリティ脆弱性の検出にはsafetyを使っていますが、Pipenvに組み込まれているのでインストールする必要はありません。

シェルでのコマンド補完

Pipenvのコマンドはシェルで補完できます。.bashrc.zshrcなどに以下を追加します。

eval "$(pipenv --completion)"

パッケージの依存グラフの表示

インストールしたパッケージの依存パッケージを表示できます。

pipenv graph

結果

Keras==2.1.6
  - h5py [required: Any, installed: 2.7.1]
    - numpy [required: >=1.7, installed: 1.14.3]
    - six [required: Any, installed: 1.11.0]
  - numpy [required: >=1.9.1, installed: 1.14.3]
  - pyyaml [required: Any, installed: 3.12]
  - scipy [required: >=0.14, installed: 1.0.1]
    - numpy [required: >=1.8.2, installed: 1.14.3]
  - six [required: >=1.9.0, installed: 1.11.0]

それとは逆に、依存パッケージがどのパッケージから使われているかも表示できます。

pipenv graph --reverse

結果

numpy==1.14.3
  - h5py==2.7.1 [requires: numpy>=1.7]
    - Keras==2.1.6 [requires: h5py]
  - Keras==2.1.6 [requires: numpy>=1.9.1]
  - matplotlib==2.2.2 [requires: numpy>=1.7.1]
  - scipy==1.0.1 [requires: numpy>=1.8.2]
    - Keras==2.1.6 [requires: scipy>=0.14]
  - tensorboard==1.8.0 [requires: numpy>=1.12.0]
    - tensorflow==1.8.0 [requires: tensorboard<1.9.0,>=1.8.0]
  - tensorflow==1.8.0 [requires: numpy>=1.13.3]

まとめ

PipenvによってPythonのプロジェクトを簡単に扱えるようになりました。

  • パッケージ管理を一元化できる様になった。
  • アプリの起動、テスト、静的解析などのコマンドも抽象化できるようになった。
  • 普段は仮想環境を意識しなくてよい。
  • 依存ライブラリのセキュリティ脆弱性の検証もできる。
  • pyenvがあればPipfileからライブラリだけでなくPythonのインストールまで自動化できる。

Todo

  • huskeyのようなgit commit時の静的解析やgit push時のテスト
  • ファイルの変更を検知した自動再起動や実行
  • テスト: toxやTravis-CIでのCI

適宜アップデートする予定です。