在python

时间:2016-03-08 09:39:21

标签: python asynchronous python-asyncio

我想在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",)>

我不确定我是否理解是否正确,请提供建议。

1 个答案:

答案 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。 如果应用程序的大部分构建在异步库之上,但只有相对较小的部分使用线程池 - 那很好。