celeryでclassのmethodを利用する方法
概要
django+celeryを利用して、あるクラスの処理を非同期に処理しようとした際に、メソッドを利用するところで、「takes exactly 2 arguments (1 given)」と怒られた。
(selfが渡っていないときなどによく見るエラー)
調べてみると、celeryから、classのmethodを利用する際には、それに応じた手続きが必要なようであったので、以下その方法を記載しておく。
背景
あるクラス(Converterというクラス)に含まれるメソッド"convert()"を利用した際に、「raised exception: TypeError('convert() takes exactly 2 arguments (1 given)',)」と怒られた。
本家のドキュメント(celery.contrib.methods)にあったので、それを参考に、後述の様に書き換えたところ動いた。
上記サイトによれば、taskのベースクラスが新しくなったそうで、これまでのような古い書き方は推奨されないらしい。
The task must use the new Task base class (celery.Task), and the old base class using classmethods (celery.task.Task, celery.task.base.Task).
This means that you have to use the task decorator from a Celery app instance, and not the old-API:
from celery import task # BAD
from celery.task import task # ALSO BAD
(略)
ということで、以下自分の使ったクラス(Conveterクラス)を例に、手順を示す。
元々のConverterクラスはこんな感じ。
from celery import task class Converter(object): def __init__(self, converter="xxx", file_format="yyy"): pass # いろいろ処理 @task() def convert(self, in_file): pass # いろいろ処理
以下の様に書き換えた。(from celery ... --> from celery.contrib.methods ...)
from celery.contrib.methods import task class Converter(object): def __init__(self, converter="xxx", file_format="yyy"): pass # いろいろ処理 @task() def convert(self, in_file): pass # いろいろ処理
あとは、普通に、非同期実行でOK。
$ python Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) [GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from xxx.converter import Converter >>> c = Converter() >>> c.convert.delay("xxx/aaa.bbb") <AsyncResult: 43c72c43-f535-45f0-b6a2-2ed60897c352> >>>
celery側のログ
[2012-12-02 03:32:37,116: INFO/MainProcess] Task xxx.converter.convert[50e07a93-6eef-48f8-84f8-249d03354089] succeeded in 0.123465061188s: 'xxx/aaa.bbb'