[環境]
+ OS Ubuntu 16.04
+ Python 3.5.2

Pythonで以下のようなデコレータを定義したとします。

def trace(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        print('Enter Func')
        try:
            ret = f(*args, **kwargs)
        except:
            print('EXCEPTION')
            raise
        print('Leave Func')
        return ret
    return wrapper

このデコレータは通常の関数であれば期待通り動作します。

def func():
    print('Hello')

func = trace(func)
func()

<< Enter Func
<< Hello
<< Leave Func

しかし、ジェネレータ関数に対しては、期待通り動作しません。

def generator_func():
    print('Start Generator')
    for i in range(3):
        yield(i)

generator_func = trace(generator_func)
for x in generator_func():
    print(x)

<< Enter Func
<< Leave Func
<< Start Generator
<< 0
<< 1
<< 2

期待する出力は下記の通りです。このような出力を得るためのデコレータは定義可能でしょうか?

<< Enter Func
<< Start Generator
<< 0
<< 1
<< 2
<< Leave Func

その関数がgeneratorかどうかは下記のコードで判定できるようなので、ジェネレータ用にデコレータが工夫可能であれば、デコレータ内でジェネレータを判定して、分岐させようと考えています。

import inspect
inspect.isgeneratorfunction(func)