我想在Python中使用asyncio模块来实现并行执行请求任务,因为我当前的请求任务按顺序工作,这意味着它是阻塞的。
我已经在Python中阅读了asyncio模块的文档,并且我已经编写了一些简单的代码,但是它并没有像我想的那样工作。
import asyncio
class Demo(object):
def demo(self):
loop = asyncio.get_event_loop()
tasks = [task1.verison(), task2.verison()]
result = loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print(result)
class Task():
@asyncio.coroutine
def version(self):
print('before')
result = yield from differenttask.GetVersion()
# result = yield from asyncio.sleep(1)
print('after')
我发现他们提供的所有示例都使用asyncio函数来使非阻塞工作,如何使自己的函数作为asyncio工作?
我想要实现的是,对于任务,它将执行请求并且不等待响应然后切换到下一个任务。当我尝试这样做时:我得到RuntimeError: Task got bad yield: 'hostname'
,主机名是我预期结果中的一项。
所以@AndrewSvetlov说,differentask.GetVersion()是一个常规的同步函数。我尝试了similar post中建议的第二种方法,即Keep your synchronous implementation of searching...blabla
@asyncio.coroutine
def version(self):
return (yield from asyncio.get_event_loop().run_in_executor(None, self._proxy.GetVersion()))
它仍然无法正常工作,现在的错误是
Task exception was never retrieved
future: <Task finished coro=<Task.version() done, defined at /root/syi.py:34> exception=TypeError("'dict' object is not callable",)>
我不确定我是否理解是否正确,请提供建议。
答案 0 :(得分:1)
更改为
@asyncio.coroutine
def version(self):
return (yield from asyncio.get_event_loop()
.run_in_executor(None, self._proxy.GetVersion))
请注意self._proxy.GetVersion
这里没有调用,但函数的引用被传递给循环执行器。
现在,GetVersion()
执行的所有IO仍然是同步的,但在线程池中执行。
它可能对您有益,也可能没有。
如果整个程序只使用基于线程池的解决方案,那么您可能需要concurrent.futures.ThreadPool
,而不是asyncio
。
如果应用程序的大部分构建在异步库之上,但只有相对较小的部分使用线程池 - 那很好。