2013年4月19日

Python の LiveReload で任意のコマンドを実行する

Python LiveReload が 0.15 にバージョンアップされ、 shell() という関数で任意のコマンドを実行できるようになりました。 自分が実装したものが取り込まれたので、簡単に紹介しておきます。

Python の Livereload 自体に関しては下記の記事で紹介しています。 ドキュメントをプレインテキストで書いて HTML で読む、という用途とは相性が良いと思います。

環境構築

virtualenv + pip で環境を構築します。

$ [ -d $HOME/pyvenv ] || mkdir $HOME/pyvenv
$ virtualenv --distribute $HOME/pyvenv/sphinx
$ source $HOME/pyvenv/sphinx/bin/activate
$ pip install -U "livereload>=0.15"
$ pip install Sphinx

livereload というスクリプトが利用可能になっていれば環境構築は完了です。

$ which livereload
/Users/shigeru/pyvenv/sphinx/bin/livereload

指定したファイルの更新でコマンドを実行

Sphinx を使ってドキュメントを書いている場合、 拡張子が ".rst" か ".txt" のファイルが更新されたら "make html" コマンドを実行したい、という パターンがよくあります。 .rst ファイルが更新されたら "make html" コマンドを実行させるには、 LiveReload のタスク定義ファイル - Guardfile - を次のように記述します。

Guardfile

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from livereload.task import Task
from livereload.compiler import shell

Task.add('*.rst', shell('make html'))

LiveReload(Python)で更新検知させてCompassでコンパイル、ついでにブラウザもリロードする という記事にあるように、 sass/screen.scss が変更されたら compass compile を実行する、 という処理は次のように記述できます。(動かしてませんが。。。)

Guardfile

#!/usr/bin/env python

from livereload.task import Task
from livereload.compiler import shell

Task.add('sass/screen.scss', shell('compass compile'))

shell() 関数の追加により、簡単なコマンドライン処理は独自の関数を記述しなくても実行できるようになりました。 上記のサンプルは Compiler に関するドキュメントにも追記しておきました。 なお、既存のエイリアス (lessc, uglifyjs, slimmer, coffee) はそのまま残してあります。 Web アプリのフロントエンド開発に使うためには有用だと思います。

実装の中身

実装におけるちょっとしたことをメモしておきます。

関数の部分適用

Task.add の2番目の引数には呼び出し可能な関数を渡す必要があります。 しかし、 shell() 関数にはコマンドラインの文字列を渡したいので、 関数の戻り値が呼び出し可能でなければなりません。

このような処理を実現するためには functools モジュールの partial を使うと良いと思います。

NULL デバイス

ある関数が引数にファイル風オブジェクトを受け取り、処理の内部でそこに書き込むことが多々あります。 しかし、実際には何も書き込みたくない、という状況もあります。 たとえば、cron で定期実行ジョブを設定する場合に出力を /dev/null に捨てる場合があります。 subprocess.call() などを使う場合には気になる点かもしれません。

Windows だとどんなものが該当するのか分かりませんが、 Python ではそれらを抽象化して os.devnull を提供してくれています。 これを使うことで、プラットフォームに依存しない実装を実現できることでしょう。

Tornado のバージョンアップ

Python LiveReloadTornado に依存しています。 その Tornado が4月にバージョン3になりました。 このメジャーバージョンアップによって、いくつかのインターフェイスが変更になったようです。

LiveReload では enable_pretty_logging を使っていますが、 これが tornado.log から tornado.options に変わったようです。 実行環境によっては色々なバージョンの組み合わせがあるかもしれませんので、 もしかしたら動かないことがあるかもしれません。 エラーが起こる場合は virtualenv で環境を作り直すのも一つの手かもしれません。

終わりに

Python LiveReload で任意のコマンドを実行できるようになりました。 エディタで何かを書いて、コマンドを実行して、ブラウザをリロードして確認する、 というサイクルの作業には役立つと思います。 README を reST や markdown で書く場合などには便利かもしれませんね。

コメントを投稿