Hatena::ブログ(Diary)

作業記録/備忘録(仮) このページをアンテナに追加 RSSフィード

2012/12/02

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'
Connection: close