Python 3.5异步用于阻止ioloop [英] Python 3.5 async for blocks the ioloop

查看:61
本文介绍了Python 3.5异步用于阻止ioloop的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个处理程序的简单aiohttp服务器。
第一个在 async for 循环中进行一些计算。第二个只是返回文本响应。 not_so_long_operation 返回第30个斐波那契数,其递归实现最慢,大约需要一秒钟的时间。

I have a simple aiohttp-server with two handlers. First one does some computations in the async for loop. Second one just returns text response. not_so_long_operation returns 30-th fibonacci number with the slowest recursive implementation, which takes something about one second.

def not_so_long_operation():
    return fib(30)

class arange:
    def __init__(self, n):
        self.n = n
        self.i = 0

    async def __aiter__(self):
        return self

    async def __anext__(self):
        i = self.i
        self.i += 1
        if self.i <= self.n:
            return i
        else:
            raise StopAsyncIteration

# GET /
async def index(request):
    print('request!')
    l = []
    async for i in arange(20):
        print(i)
        l.append(not_so_long_operation())

    return aiohttp.web.Response(text='%d\n' % l[0])

# GET /lol/
async def lol(request):
    print('request!')
    return aiohttp.web.Response(text='just respond\n')

当我尝试获取 / 然后是 / lol / ,它仅在第一个完成时才给出第二个响应。

我在做错什么,如何使索引处理程序在每次迭代时释放ioloop?

When I'm trying to fetch / and then /lol/, it gives me response for the second one only when the first one gets finished.
What am I doing wrong and how to make index handler release the ioloop on each iteration?

推荐答案

您的示例没有 yield点等待语句)以在任务之间进行切换。
异步迭代器允许 __ aiter __ / <$ c $中使用 await c> __ anext __ ,但不要将其自动插入代码中。

Your example has no yield points (await statements) for switching between tasks. Asynchronous iterator allows to use await inside __aiter__/__anext__ but don't insert it automatically into your code.

说,

class arange:
    def __init__(self, n):
        self.n = n
        self.i = 0

    async def __aiter__(self):
        return self

    async def __anext__(self):
        i = self.i
        self.i += 1
        if self.i <= self.n:
            await asyncio.sleep(0)  # insert yield point
            return i
        else:
            raise StopAsyncIteration

应该按预期工作。

在实际应用中很可能不需要等待asyncio.sleep(0)调用,因为您将等待数据库访问和类似的活动。

In real application most likely you don't need await asyncio.sleep(0) calls because you will wait on database access and similar activities.

这篇关于Python 3.5异步用于阻止ioloop的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆