2013-12-22 41 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