2013-12-22 36 views
3

我正在編寫一個框架,框架將調用用戶提供的函數。maybeDeferred analog asyncio

我想允許使用提供的函數,是以下任何一種:

  • 純函數
  • 函數返回asyncio.Future
  • 一個asyncio.coroutine

即,用戶函數可以是同步的也可以是異步的,而框架並不提前知道,但需要應對所有變體。

Twisted hasdefer.maybeDeferred爲此。什麼是asyncio的方式?

我有類似如下(全碼here):

import types 
types.GeneratorType 

def maybe_async(value): 
    if isinstance(value, types.GeneratorType) or \ 
     isinstance(value, asyncio.futures.Future): 
     return value 
    else: 
     future = asyncio.Future() 
     future.set_result(value) 
     return future 

,然後調用用戶提供的函數f這樣的框架:

res = yield from maybe_async(f(x)) 

這個包裹任何純函數返回值爲Future - 總是。我對這種表現或其他影響感到警惕。

高於「推薦」的方式?

此外,"inline" version of above code沒有這種開銷。我怎樣才能實現兩者中的最佳效果:對於「簡單」情況沒有開銷,但是在整個框架中沒有檢查異步的代碼重複?

+0

'maybeDeferred'接受一個函數,而不是一個原因,函數的結果。如果'f'引發同步異常,你會發生什麼? –

+0

@ Jean-PaulCalderone抓住它(所有變種都一樣):https://github.com/oberstet/scratchbox/blob/master/python/asyncio/test3.py#L96 – oberstet

+1

'res = yield from asyncio.coroutine( f)(x)' – jfs

回答

2

綜上所述,似乎有兩(主)選項:

成語1:

res = f(x) 
if yields(res): 
    res = yield from res 

其中

def yields(value): 
    return isinstance(value, asyncio.futures.Future) or inspect.isgenerator(value) 

成語2 :

res = yield from asyncio.coroutine(f)(x) 
+0

無關:您可以使用'asyncio.Future'名稱而不是'asyncio.futures.Future'。 – jfs