我们说我有一堆协同程序。应使用yield from
调用这些协同程序。我怎么能检测到我犯了一个错误并像子程序一样直接调用了协程?
以下是一个示例代码:
import asyncio
@asyncio.coroutine
def A(msg):
print(msg)
yield from asyncio.sleep(1)
@asyncio.coroutine
def B():
while True :
yield from A('1')
A('2')
yield from A('3')
loop = asyncio.get_event_loop()
loop.run_until_complete(B())
输出:
1
3
1
3
1
3
...
调用coroutine就像子例程一样,但不会引发异常或阻塞事件循环,所以失败模式非常安静。
答案 0 :(得分:4)
我在你的代码中添加了check_iterator函数。如果你用这个函数装饰你的协程,它将打印信息,如果你的协程是直接调用的,并且不能使用__iter__
访问。根据您的实际代码,您可能需要进行更完整的实现并包装__next__
。不过,这可能会稍微降低一点。
import asyncio
import functools
class IterWrap(object):
def __init__(self, f, *args, **kwds):
self.iterated = False
self.info = [f, args, kwds]
self.f = f(*args, **kwds)
def __iter__(self):
self.iterated = True
return iter(self.f)
def __del__(self):
if not self.iterated:
print("Did not yield: %s" % self.info)
def check_iterator(f):
@functools.wraps(f)
def wrapper(*args, **kwds):
return IterWrap(f, *args, **kwds)
return wrapper
@check_iterator
@asyncio.coroutine
def A(msg):
print(msg)
yield from asyncio.sleep(1)
@asyncio.coroutine
def B():
while True :
yield from A('1')
A('2')
yield from A('3')
loop = asyncio.get_event_loop()
loop.run_until_complete(B())
在Python 3.4上运行它的结果是:
1
Did not yield: [<function A at 0xb6e3189c>, ('2',), {}]
3
1
Did not yield: [<function A at 0xb6e3189c>, ('2',), {}]
3
1
Did not yield: [<function A at 0xb6e3189c>, ('2',), {}]
3
1
Did not yield: [<function A at 0xb6e3189c>, ('2',), {}]
3