Hatena::ブログ(Diary)

def __mopemope__(self, *args, **kwargs): このページをアンテナに追加 RSSフィード

 | 

2009-03-03

[]virtualenv

最近流行りのvirtualenvですが、仕組み的なものにあまり触れられてないように

思えたので書いてみます。

機能

とりあえずvirtualenvの機能は

です。

これを実現する仕掛けはそれほど難しくありません。

(virtualenv自体も基本的に1ファイルモジュールです。)

とりあえず簡単に見ていきます。

ライブラリパス

まっさらライブラリを持った状態のpython環境はどうやって作るのでしょう?

python自分自身のパスの上位のlib/pythonx.xをライブラリとして認識します。

pythonソースからprefix指定でビルドした事があればわかると思います。)

.
|-- bin
|   `-- python
`-- lib
    `-- python2.5
        `-- ここが標準ライブラリとして読み込まれる

virtualenvはこの仕様を利用しています。

ではライブラリまっさら環境を自前で作ってみましょう。

適当dirを作ってbin/pythonには/usr/bin/python2.5など使用したいpythonバイナ

リをコピーして置きます。

そしてlib/python<バージョン>のdirを作ります。

しかし、このままでは標準ライブラリパスとして認識しないっぽいです。なので

os.pyをコピーして置いてやります。

.
|-- bin
|   `-- python
`-- lib
    `-- python2.5
        `-- os.py

これで最小限な環境は完成です。

bin/pythonを実行してライブラリパスが変わっているか確認してみて下さい。

よく分からない場合は

bin/python -c "import sys;print sys.path"

を実行するとライブラリを読み込むパスが変わっていると思います。

virtualenvでは環境を新たに作るとlib/pythonx.x以下に元々の標準ライブラリ

のみをコピーします。

作った環境lib/pythonx.x以下を見てみるとわかると思います。

サードパーティライブラリ

virtualenvではサードパーティライブラリを含めるかどうか選ぶ事ができます。

(--no-site-packagesで含めない)

通常サードパーティライブラリパスをいじるにはsite.pyで変更します。

virtualenvも同じ仕組みです。

virtualenvは環境を作る際に独自のsite.pyを置きます。

このsite.pyではno-global-site-pakcages.txtがあるかないかで元のサードパーテ

ライブラリパスを含めるかどうか判断します。

これも作った環境lib/pythonx.x以下のsite.pyを見てみるとわかると思います。

インストール先の変更

virtualenvを使うとインストール先が新しく構築した環境になります。

これはdistutilsの仕組みを利用しています。

virtualenvはsite.pyの時と同様にdistutilsを独自のものに置き換えます。

通常、distutils.sysconfig.get_python_lib()はサードパーティライブラリのイン

ストール先を返しますがvirtualenvではこの辺の関数をごっそり置き換えます。

関数で返るパスコントロールすることでインストール先をうまく切り替えます。

これも作った環境lib/pythonx.x/distutils/__init__.pyを見てみるとわかる

と思います。

activate

virtualenvでは構築した環境のbin/pythonを叩かない限りその環境でうまく動作し

ません。

(上記のライブラリパスの問題があるから)

なので通常はactivate機能を使います。

source bin/activate

activateは単なるshellです。

エディタで開くとわかります)

activateはシンプルな機能です。

通常のPATHの前に構築した環境のbinをセットしているだけです。

なのでpythonと叩いた場合に先に構築したbin/pythonというだけの話です。

bootstrap

virtualenvの真骨頂はこのbootstrap機能です。

bootstrapは

を行ってくれます。

また事後処理部は拡張することも可能です。

virtualenvがインストールされていなくてもbootstrap用のスクリプトがあれば

環境構築を行うことができます。

また、setuptoolsが入るのでその他に必要なライブラリインストールしたり

することができます。

つまり開発に必要な環境を既存の環境を壊すことなく構築できるわけです。

例えば開発に必要なライブラリを大量に入れないといけないケースなどbootstrap

さえあればvirtualenv環境で必要なライブラリインストールを一発で行うことが

できます。

開発の現場では誰かが一人、bootstrapを書き、そいつをみんなが実行することで

同じライブラリバージョン環境が構築できるわけです。

bootstrapの構築

とはいえbootstrapスクリプトはどう書けばいいのでしょう?

virtualenvにはbootstrapを書くための仕組み用意されています。

create_bootstrap_script関数を使えば簡単に作ることができます。

例としてdjangoのbootstrapを書いてみます。

create_django_env.py
import os
import virtualenv

here = os.path.dirname(os.path.abspath(__file__))
base_dir = os.path.dirname(here)
script_name = os.path.join(base_dir, 'django-bootstrap.py')
extra_text = open(os.path.join(here,'_installer.py')).read()

def main():
    text = virtualenv.create_bootstrap_script(extra_text)
    if os.path.exists(script_name):
        f = open(script_name)
        cur_text = f.read()
        f.close()
    else:
        cur_text = ''
    print 'Updating %s' % script_name
    if cur_text == text:
        print 'No update'
    else:
        print 'Script changed; updating...'
        f = open(script_name, 'w')
        f.write(text)
        f.close()

if __name__ == '__main__':
    main()

拡張部は_installer.pyに記述します。

_installer.py
import os
import sys

#def extend_parser(parser):
#    parser.add_option(
#            '--pip',
#            dest='use_pip',
#            action='store_true',
#            default=False,
#            help='Use pip instead of easy_install (experimental)')

def after_install(options, home_dir):
    if sys.platform == 'win32':
        bin = "Scripts"
    else:
        bin = "bin"

    pip = os.path.join(home_dir,bin,'pip')
    easy_install = os.path.join(home_dir,bin,'easy_install')
    execute(easy_install,'pip')

    def execute(cmd,params):
        cmd = cmd + ' ' + params
        print "Running command...."
        print cmd
        subprocess.call(cmd.split())

    execute(pip,'install django')
    #execute(pip,'install python-mysql')
    #execute(pip,'install psycopg2')
    execute(pip,'install werkzeug')
    execute(pip,'install python-memcached')
    execute(pip,'install -e svn+http://django-command-extensions.googlecode.com/svn/trunk/')

とりあえずシンプルなもの。

DatabaseDriver部はコメントアウトしていますが、exetend_parser部で拡張して選択するようにもできます。

またpythonバージョンも指定することができますが今回はしていません。

create_django_env.pyを実行するとdjango-bootstrap.pyが出来ます。

このdjango-bootstrap.pyはvirtualenvと同じ引数を取ります。

python django-bootstrap.py --no-site-packages django-env

とやるとdjango-envという名前環境を構築します。

構築する際に使うであろう

もまとめてインストールされます。

djangoだと依存が少ないのでありがたみが少ないですが、大量にライブラリインストールするケースなどでは

かなり重宝します。

今のところbootstrapを提供しているものは少ないですが、今後増えてくるのではないかと思います。

(tg2がbootstrapを提供しています。大量に依存があるから)

まとめ

virtualenvを使う意義は

だと思います。

特にbootstrapは複数人が同じ環境を構築するという作業を簡潔化してくれます。

(他にも何かを配布する際にも重宝する)

みんなもvirtualenv使おう!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

 | 
Connection: close