HDE BLOG

コードもサーバも、雲の上

Pythonでvirtualenvの構築を自動化する

おはこんばちは!! 尾藤 a.k.a. BTOです。

pythonで開発環境を構築する時は、virtualenvを使うことが多いかと思います。 弊社のプロダクトでもvirtualenvを使って、各開発者の環境を統一しています。

そこで問題になるのがvirtualenvの構築です。 virtualenvの構築を主導でやっていると、手作業によるミスが起きやすいですし、何より最初からすることが決まっている処理は自動化したいものです。

そこで、virtualenvの環境を自動で構築するために、virtualenvのbootstrapを使用しています。

virtualenv bootstrap script を作っておけば、

% python create.py ~/.venv/your-project

みたいにして、コマンド一発でvirtualenvの構築と必要なライブラリのインストールが一発でできるようになり、各開発者の環境統一が簡単にできるようになります。

virtualenv bootstrap

virtualenvにはbootstrapという機能がついています。 bootstrapを使うと、virtualenvの構築任意の事後処理を1発で実行するbootstrap scriptを生成してくれます。 プロジェクトでbootstrap scriptを作っておけば、コマンドを1発実行するだけで、同じライブラリ、バージョンを持ったvirtualenvを構築できます。

bootstrap scriptの生成

では、どのようにしてbootstrap scriptを生成すればいいのでしょうか。 virtualenvにはbootstrap scriptを生成する機能がついています。

virtualenv.create_bootstrap_script() を呼び出すと、bootstrap script用の文字列を返してくれますので、あとはそれをbootstrap script fileに書き出すだけです。 virtualenv.create_bootstrap_script() には事後処理を実装するスクリプトの文字列を渡すことができます。

#!/usr/bin/env python

import os
import virtualenv

extra_script = open('extra.py').read()
script = virtualenv.create_bootstrap_script(extra_script)
f = open('create.py', 'w')
f.write(script)
f.close()

freeze.py

これはvirtualenv bootstrap scriptを生成するfreeze.pyです。 ここではextra.pyから事後処理のスクリプトを読み込み、create.pyというvirtualenv bootstrap scriptを生成しています。

import os

def after_install(options, home_dir):
    pip = os.path.join(home_dir, 'bin', 'pip')
    os.system(pip + ' install Fabric')
    os.system(pip + ' install boto')
    os.system(pip + ' install pep8')
    os.system(pip + ' install tornado')

extra.py

extra.pyはこんな感じでafter_installにvirtualenvインストール後の処理を書きます。 ここで必要なライブラリをインストールするようにすれば、virtualenvの構築とライブラリのインストールが一発でできるようになります。

これで準備が整ったので、freeze.pyを実行すると、create.pyを生成してくれます。

% python freeze.py

できたcreate.pyをリポジトリにコミットすれば、他の開発者にも同様な環境を簡単に構築できます。

requirements.txtを使う

pythonのプロジェクトではrequirements.txtというファイルがよく使われます。 これはただのpip freezeの出力結果なのですが、そのプロジェウトで必要なライブラリやバージョンを簡潔に表現することができます。

requirements.txtの生成は簡単です。 pip freeze の結果をファイルに書き出しましょう。

% pip freeze > requirements.txt

それでは先ほどのvirtualenv bootstrap scriptでrequirements.txtを使うようにしてみましょう。 それにはextra.pyでpip installしている部分をrequirements.txt経由でインストールするように変更するだけでできます。

import os

def after_install(options, home_dir):
    pip = os.path.join(home_dir, 'bin', 'pip')
    os.system(pip + ' install -r requirements.txt')

extra.py

これで、今後はrequirements.txtを更新するだけでよくなりました。

wheelを使う

ここまでで、環境構築の自動化がかなり進みました。 しかし、現状ではpipでライブラリのインストールを最初から行うため時間がかかってしまいます。 毎回pipサーバに取りに行くのも無駄です。 コンパイル済みのパッケージがローカルにあれば問題は一気に解決します。 そのためにwheelというものを使います。

wheelはpythonのパッケージを配布するためのフォーマットです。 wheelのパッケージはコンパイル済みのため、インストールが高速にできます。 事前にwheelパッケージを作ってローカルに持っておけば、pipサーバにアクセスせずに高速にインストールすることができるようになります。

wheelパッケージを作るのは簡単で、次のようにコマンドを実行するだけです。

% pip wheel -r requirements.txt

コマンドを実行すると、wheelhouseというディレクトリにwheelパッケージが作られます。 拡張子は.whlです。

では今度はwheelパッケージを使ってインストールするようにしてみましょう。 after_installのところで、wheelパッケージを使ってインストールするように変更するだけです。

import os

def after_install(options, home_dir):
    pip = os.path.join(home_dir, 'bin', 'pip')
    os.system(pip + ' install --use-wheel --no-index --find-links=wheelhouse')

extra.py

これでpipサーバにアクセスする必要もなくなり、インストールも高速にできるようになりました。

結論

HDEでは英語で人狼を開催します。 ご興味のある方はご連絡ください。

Shibuya English Werewolf Party vol.2 | Facebook