django-celeryで非同期処理クイックスタートガイド
django-celery で非同期処理をやる。
サクッと非同期処理を試せちゃうような、クイックスタートガイド をメモがてら書いていく。
インストール
まずはインストールから。
pip を使って Django と django-celery をインストールする。
% pip install Django
% pip install django-celery
おわり。
バージョンは以下のようになった
% pip freeze
Django==1.5
amqp==1.0.10
anyjson==0.3.3
billiard==2.7.3.23
celery==3.0.16
django-celery==3.0.11
kombu==2.5.8
python-dateutil==1.5
pytz==2013b
wsgiref==0.1.2
設定
インストールできたら Django のプロジェクト asynctest と、 アプリケーション caculator を作ってみる。
% django-admin.py startproject asynktest
% cd asynktest
% python manage.py startapp caculator
まずは設定ファイル (asynctest/asynctest/settings.py) に django-celery と先ほど作った caculator 、それとあと 裏方の kombu.transport.django をいれてやる。
INSTALLED_APPS = (
...
'djcelery',
'kombu.transport.django',
'caculator',
)
こんなかんじに。
さらに、 django-celery に関する設定を追記する。
###### django-celery configuations ######
from djcelery import setup_loader
setup_loader()
BROKER_URL = 'django://'
# Tasks will be executed asynchronously.
CELERY_ALWAYS_EAGER = False
あとはDBと同期すればOK。
Note
django-kombu をインストールしなくても最近の kombu と上記の設定で Django のDBをブローカーとして使えるよう。 django-celery インストールの段階で kombu もインストール されてくれるので、とくに kombu を意識する必要がなくなって しまった。
非同期処理させるもの
さて肝心の処理をおこなう関数を書く。 caculator/tasks.py を以下のように書いた。
import time
from celery import task
@task
def add(a, b):
time.sleep(10)
return a + b
task でデコレートしてあげるだけで良い。 add 関数は10秒スリープしてくれるという親切設計なので、 存分に非同期を味わうことができる。
あと、モジュール名は tasks.py にしましょうね。
実行してみる
準備ができたので非同期を味わってみる。 まずは Celery 氏を起動。
% python manage.py celeryd -l info
別のシェルから manage.py shell を起動。
% python manage.py shell
打っていく。
>>> from caculator.tasks import add
>>> add(1, 2) # 10秒かかる
3
>>> add.run(1, 2) # 10秒かかる
3
>>> result = add.delay(1, 2) # 非同期で実行するには delay
>>> result.ready() # ready で終了したかがわかる
False
>>> result.ready() # マダァ?(・∀・ )っ/凵⌒☆チンチン
True
>>> result.get() # 終わってたら get でとる
3
>>> # 処理終わってないのに get すると、
>>> # 値が返るまで待ってしまう
>>> # タイムアウトしたい
>>>
>>> result = add.delay(3, 4) # もっかい計算
>>> result.get(timeout=3) # 3秒間だけ待つ
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/path/to/celery/result.py", line 109, in get
interval=interval)
File "/path/to/celery/backends/base.py", line 186, in wait_for
raise TimeoutError('The operation timed out.')
TimeoutError: The operation timed out.
>>> # 3秒以内に終わらなかったら TimeoutError
>>> result.get(timeout=3)
7
>>> # 3秒以内なら結果が返る
こんなかんじで使えます。 やったね。非同期処理ができたよ。
重い処理があれば非同期でやらせて、ポーリングして結果待つとか サクッと書けてしまう。 Django 内で完結してできるから分かりやすくて楽。 django-celery 覚えていて損ないかと思う。
参考: