簡體   English   中英

Asyncio python - TypeError: A Future, a coroutine or an awaitable is required

[英]Asyncio python - TypeError: A Future, a coroutine or an awaitable is required

異步函數之一返回異步生成器對象。 我添加了 loop.run_until_complete(func()),但它仍然拋出錯誤“TypeError: A Future, a coroutine or an awaitable is required”。 下面是代碼。 我正在嘗試從 Neo4j 異步獲取記錄。 我從 GitHub 獲得了異步“Neo4j 類。我是這個異步概念的新手。

from concurrent import futures
import neo4j
from neo4j import GraphDatabase, basic_auth
import time
import traceback
import asyncio 

RETRY_WAITS = [0, 1, 4]  # How long to wait after each successive failure.
class Neo4j:
    """Neo4j database API."""
    def __init__(self, config, loop):
        self.config = config        
        self.loop = loop
        self.executor = futures.ThreadPoolExecutor(max_workers=30)
        for retry_wait in RETRY_WAITS:
            try:
                self.init_driver()
                break
            except:
                if retry_wait == RETRY_WAITS[-1]:
                    raise
                else:
                    print('WARNING: retrying to Init DB; err:')
                    traceback.print_exc()
                    time.sleep(retry_wait)  # wait for 0, 1, 3... seconds.

    def init_driver(self):
        auth = basic_auth(self.config['user'], self.config['pass'])
        self.driver = GraphDatabase.driver(self.config['url'], auth=auth)

    async def afetch_start(self, query):
        session = self.driver.session(access_mode=neo4j.READ_ACCESS)
        def run():
            return session.run(query).records()
        return session, await self.loop.run_in_executor(self.executor, run)

    async def afetch_iterate(self, session, iter):
            def iterate():
                try:
                    return next(iter)
                except StopIteration:
                    return None
            while True:
                res = await self.loop.run_in_executor(self.executor, iterate)
                if res is None:
                    return
                else:
                    yield dict(res)

    async def afetch(self, query):
        for retry_wait in RETRY_WAITS:
            try:
                session, iter = await self.afetch_start(query)
                break
            except (BrokenPipeError, neo4j.exceptions.ServiceUnavailable) as e:
                if retry_wait == RETRY_WAITS[-1]:
                    raise
                else:
                    await asyncio.sleep(retry_wait)
                    await self.loop.run_in_executor(self.executor, self.init_driver)
        async for x in self.afetch_iterate(session, iter):
            yield x

        await self.loop.run_in_executor(self.executor, session.close)


    async def afetch_one(self, query):
        async for i in self.afetch(query):
            return i
        return None

    async def aexec(self, query):
        async for i in self.afetch(query):
            pass
        return


config={'url':"bolt://localhost",'user':'neo4j','pass':'pwd'}    
loop=asyncio.get_event_loop()    
n=Neo4j(config,loop)    
loop.run_until_complete(n.afetch("MATCH(p:Person)-[:Acted_in]->(mv:Movies) RETURN p.name as actors"))
loop.close()

- 編輯

我已經修改了代碼以正常工作。 查詢返回 218K 行,提取完整列表需要 5 分鍾,而 C# 中的相同異步操作只需 2 秒即可完成。 看起來上面的代碼仍然沒有進入異步

如果沒有可重現的例子,很難說到底發生了什么,但我會猜測一下。 您可能在循環中傳遞異步生成器對象,您不應該這樣做。 使用異步生成器的一種方法是使用async for 下面是例子:

import asyncio


async def func():  # async generator
    yield 1
    yield 2
    yield 3


async def main():
    async for i in func():  # get values from async generator
        print(i)


asyncio.run(main())  # can be used instead of loop.run_until_complete(main())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM