Help us understand the problem. What is going on with this article?

既存プロジェクトに pipenv を導入した方法

みなさん pipenv を使ってますか? まだ pip ですか?

最近、pipenv を導入した際に必要だった作業を紹介します1

pipenv とは何か?なぜ pipenv なのか?

pipenvpip のラッパーで、RubyでいうBundlerです。pip単体でもライブラリの管理はできるのですが、pipenv の方が色々便利です。

pipと同様に Python Packaging Authority が管理しています

詳しくはドキュメントQiitaの記事 をご覧ください。

setup.py や requirements.txt を削除

今回 pipenv 化したのは アプリケーション です。

PyPIに公開したりする必要はないので、setup.py の中身は最小限を残して削除します。

 setup(
     name='hoge',
     version='1.4.5',
     packages=find_packages(exclude=['test']),
-    python_requires='==3.6.3',
-    install_requires=[
-        'cx_Oracle==5.3',
-        'pandas==0.23.0',
-        'PyYAML==3.12'
-    ],
-    extras_require={
-        'dev': [
-            'yapf==0.20.0',
-            'mypy==0.560'
-        ]
     package_data={'hoge': ['res/*']},
     entry_points={
         'console_scripts': [
             'hoge = hoge.cli:main',
         ],
     },

Pipfile の追加

Pipfile を追加し、setup.py から削除した内容を代わりに書き込みます。

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

[packages]
hoge = {editable = true, path = "."} # setup.py を読み込むため
cx_Oracle = "==5.3"
pandas = "==0.23.0"
PyYAML = "==3.12" # 本来は "*" を指定するべき(後述)

[dev-packages]
yapf = "==0.20.0"
mypy = "==0.560"

[requires]
python_full_version = "3.6.3" # バージョンを厳密に指定

ちなみに、[requires]python_version = "3.6" ではなく python_full_version = "3.6.3"を指定しています。パッチバージョンの違いにより不具合が生じるリスクはないとも言えませんし、バージョンごとにPythonインタープリタを用意するのは難しくないので、python_full_version を指定するのをオススメします。

デプロイスクリプトの変更

今までは、こんなシェルスクリプトでデプロイしていました。

# pipenv以前

mkdir "$INSTALL_DIR" # 所定のディレクトリを作成
pushd "$INSTALL_DIR"
  # ソースコードをコピー
  git -C "$REPO_DIR" archive --format=tar "$VERSION" | tar -xf -

  # 仮想環境を作り、そこにインストール
  "$PYTHON" -m venv .venv
  .venv/bin/pip install .
popd > /dev/null

pip installpipenv install に差し替えます。

# pipenv化

mkdir "$INSTALL_DIR" # 所定のディレクトリを作成
pushd "$INSTALL_DIR"
  # ソースコードをコピー
  git -C "$REPO_DIR" archive --format=tar "$VERSION" | tar -xf -

  # pipenv で 仮想環境を作り、そこにインストール
  export PIPENV_VENV_IN_PROJECT=1 
  "$PYTHON" -m pipenv install \
    --python="$PYTHON" \
    --deploy       
popd > /dev/null

なお、pipenv install にはいくつかオプションを指定しています。
本番環境へのデプロイではどれも必須でしょう。

--deploy をつける

--deploy を付けると、PipfilePipfile.lock にズレがあるとき(pipenv syncし忘れた時)に、エラーにします。

本番環境へのデプロイでは必ず--deployをつけましょう。

環境変数 PIPENV_VENV_IN_PROJECT を定義する

pipenv はデフォルト設定では所定のディレクトリにハッシュ値名の仮想環境を作ります(~/.local/share/virtualenvs/hoge-okggs9cf)。

しかしこれだと、どの仮想環境がどのデプロイに対応するのか判りにくいため、例えば、ディスク容量が足りなくなって不要な仮想環境を削除したいときに困りそうです。

PIPENV_VENV_IN_PROJECT が定義されていると、仮想環境がカレントディレクトリ下の./.venvに作られるようになります。

--python でインタープリタを指定する(pyenv を使わない)

pipenvpyenv を使っていると、自動的にインタープリタを選択してくれます。

しかし、うちの本番環境では pyenv を使っていないので、--python でインタープリタを直接指定しています。

ライブラリのアップデート

今回 pipenv を導入したツールでは、PyYAML==3.12のようにライブラリのバージョンを厳密に指定していました。しかし、単に PyYAML==3.12 のように書くのは問題があります。

というのも:

a. 単に 3.12でしか動作確認していないだけで、3.13 でも動くかもしれない(ので、できればアップデートするのが望ましい)
b. (バグや仕様変更により) 3.12 でしか動作しない。アップデートしてはいけない。

のどちらなのか判りません。

今回 pipenv を導入したツールの PyYAML は前者だったので、Pipfile を書き換えて動作確認しました。

  # Pipfile
  [packages]
  cx_Oracle = "==5.3"
  pandas = "==0.23.0"
- PyYAML = "==3.12'
+ PyYAML = "*"

一方、cx_Oracle や pandas は、このバージョンしか使えない事情があったので、バージョンを厳密に指定しています。

感想

実際の作業としては、特にハマり所はありませんでした
Pipfile の文法を覚えるのや、チームメンバーに説明するのは面倒でしたが)。

バージョンを厳密に管理できるメリットは大きいです。ぜひ pipenv の導入を。


  1. なお、導入したのは内製のレポート生成ツールでした。顧客へのレポートも生成しているので、一応トラブルがあると困るものです。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away