【发布时间】:2015-07-22 06:16:35
【问题描述】:
我对如何在 Python 3.4 中使用 asyncio 模块感到困惑。我有一个用于搜索引擎的searching API,并且希望每个搜索请求可以并行或异步运行,这样我就不必等待一个搜索完成来开始另一个搜索。
这是我用原始搜索结果构建一些对象的高级搜索 API。搜索引擎本身正在使用某种异步机制,所以我不会打扰。
# No asyncio module used here now
class search(object):
...
self.s = some_search_engine()
...
def searching(self, *args, **kwargs):
ret = {}
# do some raw searching according to args and kwargs and build the wrapped results
...
return ret
为了尝试异步请求,我编写了以下测试用例来测试我如何与 asyncio 模块交互我的东西。
# Here is my testing script
@asyncio.coroutine
def handle(f, *args, **kwargs):
r = yield from f(*args, **kwargs)
return r
s = search()
loop = asyncio.get_event_loop()
loop.run_until_complete(handle(s.searching, arg1, arg2, ...))
loop.close()
通过使用 pytest 运行,它会在到达r = yield from ... 行时返回一个RuntimeError: Task got bad yield : {results from searching...}。
我也尝试了另一种方法。
# same handle as above
def handle(..):
....
s = search()
loop = asyncio.get_event_loop()
tasks = [
asyncio.async(handle(s.searching, arg11, arg12, ...)),
asyncio.async(handle(s.searching, arg21, arg22, ...)),
...
]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
通过 pytest 运行这个测试用例,它通过了,但搜索引擎会引发一些奇怪的异常。上面写着Future/Task exception was never retrieved。
我想问的问题:
- 对于我的第一次尝试,通过返回函数调用的实际结果,这是使用
yield from的正确方法吗? - 我想我需要在我的第二个测试用例中添加一些睡眠来等待任务完成,但我应该怎么做呢?以及如何让我的函数调用在我的第二个测试用例中返回?
- 通过创建异步处理程序来处理请求,这是使用现有模块实现异步的好方法吗?
- 如果问题 2 的答案是否定的,是否每个客户端调用
search类都需要包含loop = get_event_loop()这类东西来异步请求?
【问题讨论】:
标签: python asynchronous python-asyncio