2016-04-05 10 views
1

私はデコレータを作成しようとしており、pyinvoke@taskデコレータと一緒に使用しています。Pyinvoke @taskデコレータで複数のデコレータを使用する

参照:場合

<Task 'zip_files'> No idea what 'zip_files' is!

どんなに:私はinv zip_files

私は出力を受け取り、実行コマンドラインから今しかし

def extract_config(func): 
    print func 

    def func_wrapper(cfg=None): 
     config = read_invoke_config(cfg) 
     return func(**config) 

    return func_wrapper 


@extract_config 
@task 
def zip_files(config): 
    import zipfile 
    ... 

、 10が@extract_configの前後に来ると、私は 呼び出しタスクの機能を失い、関数名を認識しません。

私はここで間違っていますか?

答えて

2

構文:だから、最初の行のデコレータが2行目にデコレータ後に適用される

def func(): pass 
func = deco1(deco2(func)) 

@deco1 
@deco2 
def func(): pass 

はかなり同等です。

ライブラリから使用しているtaskデコレータは、別の関数ではなくTaskオブジェクトを返します。そのため、グローバルな名前空間でラッパー関数に置き換えるときに、外部デコレータが適切な処理を行っていない可能性があります。それを動作させるには、wrapperが、Taskオブジェクトのすべての関連する動作を模倣するオブジェクトである必要があります(私はどの程度簡単か、難しいかはわかりません)。

もっと簡単な方法は、デコレータの順序を逆にすることがあります

@task 
@extract_config 
def zip_files(config): 

これはおそらく、作業に近いですが、私はそれはまだ単純な理由のためにうまくいかないと思います。 extract_configデコレータは、zip_filesとは異なる名前の関数を返します(属性を変更しようとしていないwrapperという名前の関数を返します)。したがって、Taskオブジェクトはその名前を正しく認識しません。

def extract_config(func): 
    print func 

    @functools.wraps(func) 
    def func_wrapper(cfg=None): 
     config = read_invoke_config(cfg) 
     return func(**config) 

    return func_wrapper 

これを修正するために、私はラッパー関数の中に包まれた機能の関連する属性をコピーするデコレータでfunctools.wrapsを使用してお勧めしたいです

関連する問題