首页 文章

asyncio aiohttp:为什么我的客户端仍然阻塞?

提问于
浏览
0

我正在尝试测试我的python 3.4.3 http客户端或将HTTP请求发送到服务器的应用程序 . 如果服务器因任何原因有延迟响应,我希望请求不应该阻塞,因为asyncio aiohttp应该提供异步调用:

def post(self):
    print("received post")
    print(self.request)
    print("POST Body: %s" % str(self.request.body))
    time.sleep(3)
    self.write("blah")
    self.finish()

我只是想知道为什么我的代码/ http客户端阻塞了:

import aiohttp, asyncio, async_timeout

@asyncio.coroutine
def fetch(session, url):
    with aiohttp.Timeout(30):
        try:
            response = yield from session.get(url)
            print((yield from response.read()))
            return response
        except Exception as e:
            raise e
        finally:
            try:
                response.release()
            except:
                pass

@asyncio.coroutine
def post(session, url):
    with aiohttp.Timeout(30):
        try:
            response = yield from session.post(url)
            print((yield from response.read()))
            return response
        except Exception as e:
            raise e
        finally:
            try:
                response.release()
            except:
                pass

@asyncio.coroutine
def close_connection(session):
    try:
        session.close()
    except:
        pass

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    session = aiohttp.ClientSession(loop=loop)
    try:
        for i in range(10):
            html = loop.run_until_complete(post(session, 'http://localhost:8000'))
    except Exception as e:
        print("received exception %s." % type(e).__name__)

        # Close session if not closed.
    loop.run_until_complete(close_connection(session))

我尝试做一个循环,我遍历10个URL(这里是相同的一个) . 如果它是顺序的,我希望它需要约30秒(服务器响应3秒延迟) . 对于异步,我的期望是它需要更少 .

try:
    for i in range(10):
        html = loop.run_until_complete(post(session, 'http://localhost:8000'))

是阻塞的“run_until_complete()”函数吗?如何使其无阻塞?

1 回答

  • 3

    基本上,当你使用 run_until_complete() 时,你告诉事件循环运行作为参数传递的协程并在完成时返回结果 . 简而言之, run_until_complete() 将阻塞,直到完成该操作 .

    基于您的for循环代码段 . 基本上在每个循环中, run_until_complete 将阻塞,运行协程(在此上下文中为 post ),返回结果,然后只有执行将继续下一个循环 .

    你想要做的是同时运行 post . 你可以做的是使用 asyncio.gather() .

    try:
        html = loop.run_until_complete(asyncio.gather(*[post(session, 'http://localhost:8000') for i in range(10)]))
    

相关问题