@kotyのブログ

.NETとかJavaとかPythonとか勉強会のこととかを、田舎者SEがつづります。記事のライセンスは"CC BY"でお願いします。

Django Background Tasksでお手軽バックグラウンド処理

バックグラウンドで動くバッチ処理を作りたい時にスケジューラを使うと思います。Pythonで代表的なタスクスケジューラはCeleryですかね。 でも、単に、長めの処理をキューイングしてシリアライザブルに実行していきたいといった簡単な要件だとちょっと大げさ過ぎるように感じ、他の仕掛けを探した所 Django Background Tasks というパッケージがあったの今回使ってみました。

基本的には、ドキュメントに書いてある通りですが。。

まずインストール。利用した時点でのバージョンは 1.1.0rc2でした。django-background-task (単数形)というパッケージも存在するのでご注意。今回紹介する複数形のは単数形のをforkしている模様です。

pip install django-background-tasks

settingsに設定を追記します。

INSTALLED_APPS = [
    ・・・
    'background_task',
    ・・・

キューを保持するためのテーブルを作るので、migrateします。migrationファイルが含まれていないので、makemigrationsから。migrateすると、background_taskおよびbackground_task_completedtaskというテーブルができます。

./manage.py makemigrations background_task
./manage.py migrate

タスクの定義。これだと、queue_name1というキューにキューイングし、5秒後に実行する、という設定です。

from background_task import background

@background(queue='queue_name1', schedule=5)
def some_long_duration_process(some_param1, some_param2):
    # 何か長い処理

タスクを呼び出す方の書き方です。普通にメソッドを呼んでいるように見えますが、実際にはキューイングされるだけでメソッドは呼び出されません。 @backgroundデコレータの内部でメソッド呼び出しが横取りされ、キューイングが行われます。background_taskテーブルを見ると分かるように引数はJSONシリアライズされるので、確認はしていませんがJSONシリアライズできる必要があると思われます。

# 登録側
some_long_duration_process('a', 'b')

説明の順番が若干前後しますが、予め以下のコマンドでバックグラウンドタスクを処理するプロセスを起動しておきます。

./manage.py process_tasks

サーバー構築時には、supervisordの下で動くようにしておきます。

[program:process_tasks]
command=/.../bin/python ./manage.py process_tasks --settings=my_proj.settings.prod
directory=/...
user=centos
autostart=true
autorestart=true
stdout_logfile=/.../...log ; 標準出力ログ
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=5
stdout_capture_maxbytes=1MB
redirect_stderr=true

そこそこ細かい設定もできるようですし、Celeryは大げさだなという場面では有効に使えると思いました。