asyncio.coroutine
をラップして完了までにかかった時間を返すデコレータ関数を作成しようとしました。以下のレシピには、期待どおりに機能するコードが含まれています。私の唯一の問題は、@functools.wraps
. 元のコルーチンの名前を保持するには? のソースを確認しましたasyncio.
import asyncio
import functools
import random
import time
MULTIPLIER = 5
def time_resulted(coro):
@functools.wraps(coro)
@asyncio.coroutine
def wrapper(*args, **kargs):
time_before = time.time()
result = yield from coro(*args, **kargs)
if result is not None:
raise TypeError('time resulted coroutine can '
'only return None')
return time_before, time.time()
print('= wrapper.__name__: {!r} ='.format(wrapper.__name__))
return wrapper
@time_resulted
@asyncio.coroutine
def random_sleep():
sleep_time = random.random() * MULTIPLIER
print('{} -> {}'.format(time.time(), sleep_time))
yield from asyncio.sleep(sleep_time)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
tasks = [asyncio.Task(random_sleep()) for i in range(5)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
for task in tasks:
print(task, task.result()[1] - task.result()[0])
print('= random_sleep.__name__: {!r} ='.format(
random_sleep.__name__))
print('= random_sleep().__name__: {!r} ='.format(
random_sleep().__name__))
結果:
= wrapper.__name__: 'random_sleep' =
1397226479.00875 -> 4.261069174838891
1397226479.00875 -> 0.6596335046471768
1397226479.00875 -> 3.83421163259601
1397226479.00875 -> 2.5514027672929713
1397226479.00875 -> 4.497471439365472
Task(<wrapper>)<result=(1397226479.00875, 1397226483.274884)> 4.266134023666382
Task(<wrapper>)<result=(1397226479.00875, 1397226479.6697)> 0.6609499454498291
Task(<wrapper>)<result=(1397226479.00875, 1397226482.844265)> 3.835515022277832
Task(<wrapper>)<result=(1397226479.00875, 1397226481.562422)> 2.5536720752716064
Task(<wrapper>)<result=(1397226479.00875, 1397226483.51523)> 4.506479978561401
= random_sleep.__name__: 'random_sleep' =
= random_sleep().__name__: 'wrapper' =
ご覧のとおりrandom_sleep()
、別の名前のジェネレーター オブジェクトを返します。装飾されたコルーチンの名前を保持したいと思います。これが特定の問題であるかどうかはわかりasyncio.coroutines
ません。デコレータの順序を変えてコードも試してみましたが、すべて同じ結果になりました。私がコメントすれば@functools.wraps(coro)
、私が期待したとおりにrandom_sleep.__name__
なります。wrapper
編集: この問題を Python Issue Tracker に投稿し、R. David Murray から次の回答を受け取りました。随分前。"