2013-10-16 12 views
6

セロリの後にデコレータを適用しようとしています。@taskデコレータなど。セクレタリーの@taskデコレータの後のデコレータ

@send_email 
@task 
def any_function(): 

    print "inside the function" 

私は、それはそれはドキュメントで推奨された方法で仕事を得ることができ、すなわちタスクデコレータ前にデコレータを置くことが、この場合、私は私のデコレータでタスクインスタンスにアクセスしたいと思います。 @send_emailがクラスデコレータでなければならないであろう

、これは私が成功せずにしようとしたものです:

class send_email(object): 
    ''' wraps a Task celery class ''' 
    def __init__(self, obj): 

     self.wrapped_obj = obj 

     functools.update_wrapper(self, obj) 

    def __call__(self, *args, **kwargs): 

     print "call" 

     return self.wrapped_obj.__call__(*args, **kwargs) 

    def run(self, *args, **kwargs): 

     print "run" 

     return self.wrapped_obj.__call__(*args, **kwargs) 

    def __getattr__(self, attr): 

     if attr in self.__dict__: 

      return getattr(self, attr) 

     return getattr(self.wrapped_obj, attr) 

私はコールまたは実行機能関数のprint文はどちらかに表示されるために得ることはありません作業者または発信者。

はどのように我々はそうデコレータは関数定義上記@taskを超えるだろう(クラスベースのタスク定義に頼ることなく、セロリのタスクを飾ることができます。任意の助け

ありがとう!

ミゲル

視覚的に "後" のように見える "の前に"

答えて

8

タスクデコレータはクラスを返さず、インスタンスを返します。

デコレータを最初に適用する方法ではなく、実際には「デコレータ内のタスクにアクセスするにはどうすればよいですか」と思われるようです。あなたはこれを達成するためにバインドされたタスクを使用することができ、今後3.1(開発版)で

:以前のバージョンの

def send_email(fun): 
    @wraps(fun) 
    def outer(self, *args, **kwargs): 
     print('decorated and task is {0!r}'.format(self)) 
     return fun(self, *args, **kwargs) 

    return outer 

@task(bind=True) 
@send_email 
def any_function(self): 
    print('inside the function') 

あなたがcurrent_task使用することができます。

from celery import current_task 

def send_email(fun): 

    @wraps(fun) 
    def outer(*args, **kwargs): 
     print('decorated and task is: %r' % (current_task,)) 
     return fun(*args, **kwargs) 


@task 
@send_email 
def any_function(): 
    print('inside the function') 
+0

誰も{0!r}が何をしているのか説明できますか?しばらく検索した後、私はPythonのドキュメントでこれを見つけました。 '!r'(apply repr())を使用して、値を書式設定する前に変換することができます。しかし、repr()の定義はあいまいです。ありがとう、 –

+2

@AnthonyRobertsすべてのオブジェクトは、それ自体を表示する2つの異なる方法を持っています: 'str(obj)'(これは 'obj .__ str __()'を呼びます)は、通常、ユーザインタフェースなどの表示に使用されます。 'repr(obj)'( 'obj .__ repr __()')を呼び出します。これはデバッグ目的で使用され、オブジェクトのタイプ、オブジェクトのメモリ位置、重要な属性を出力します。形式文字列 '' {0!s} ''は前者であり、 '' {0!r} ''は後者であり、古い形式では ''%s ''と' '%r" 'それぞれ、 [1]:Python2では '' __unicode__''、 '' __str__''、 '' __repr__''の3つがあります。 – asksol

+0

私は少し違う状況に閉じ込められています。この質問を考えると、最初に何らかのDB操作をしたい場合、 'any_function'の終わりです。また、 'any_function'で例外が発生したときに別のDB操作を実行できるようにしたいと思います。私は何をすべきか? – Hussain

5

例えば、この:。

@decorator1 
@decorator2 
@decorator3 
def func(): 
    pass 

は同等です:

def func(): 
    pass 

func = decorator1(decorator2(decorator3(func))) 

これは、あなたがそれを@task前に適用得るために@task@send_emailを記述する必要がありを意味します。例:

@task 
@send_email 
def any_function(): 
    print "inside the function" 
+0

を、私はそれが後に適用することにしたいです@タスク、問題は\ @タスクがクラスを返すことです – mpaf