是python3.6新更改'async for'与枚举不兼容

时间:2018-01-03 03:43:33

标签: python mongodb asynchronous python-3.6 python-asyncio

我正在尝试将我的应用程序从python2.7移动到python3.6,用于asyncio和关联库,但我发现有些功能不起作用,因为我除外。 我使用motor来异步查询mongodb,如:

async def do_query():
    song_already_processed = set()
    song_table = db.song_table
    async for index, item in enumerate(song_table.find({'lang': 'English'},
                              {'id': 1, '_id': 0, 'title': 1, 'artist.name': 1})):
        if index > 100:
            break
        if item['id'] in song_already_processed:
            continue
        song_already_processed.add(item['id'])

    print(len(song_already_processed))

但它引发了错误:

TypeError: 'AsyncIOMotorCursor' object is not iterable

我认为异步迭代器协议与普通的interator协议不同,所以枚举效果不好。我可以使用异步枚举吗?

顺便说一下,我知道很多方法可以获得100个doc并停止迭代,我只想知道如何正确使用'async for'

3 个答案:

答案 0 :(得分:3)

如果您不介意拥有外部依赖项,可以使用aiostream.stream.enumerate

<form action="/path to your php file or leave blank if both html and php are in same file">
<input type="text" name="arr" value=''>
<input type="submit" name="submit" value="submit">
</form>

请参阅此demonstrationdocumentation中的更多示例。

答案 1 :(得分:0)

Python3.6添加了asynchronous generators,可轻松实现异步枚举:

async def aenumerate(asequence, start=0):
    """Asynchronously enumerate an async iterator from a given start value"""
    n = start
    async for elem in asequence:
        yield n, elem
        n += 1

对于旧版本的Python,必须手动验证异步生成器:

class AsyncEnumerate:
    """Asynchronously enumerate an async iterator from a given start value"""
    def __init__(self, asequence, start=0):
        self._asequence = asequence
        self._value = start

    async def __anext__(self):
        elem = await self._asequence.__anext__()
        value, self._value = self._value, self._value + 1
        return value, elem

    def __aiter__(self):
        return self

答案 2 :(得分:0)

我有一个类似的问题,涉及使用异步生成器作为枚举和异步对象进行迭代。我意识到我的情况中最简单的答案是通过修改异步生成器实际上返回一个索引以返回索引,而不是通过异步来返回索引。见下文:

async def whitespace(data: List) -> tuple:
    """function to remove any whitespace in returned values"""
    for i, v in enumerate(data):
        yield i, x.strip()

async for i, x in whitespace(a_list_of_stuff):
    a_list_of_stuff[i] = x