【问题标题】:RuntimeWarning: coroutine 'UnaryStreamCall._send_unary_request' was never awaitedRuntimeWarning:从未等待协程“UnaryStreamCall._send_unary_request”
【发布时间】:2021-12-10 01:55:45
【问题描述】:

我正在尝试使用 google.cloud.firestore.AsyncClient 模块对 firebase 进行一些 API 调用。 Fire2 只是这个对象的一个​​包装器。

回溯表明它是 asyncio 的问题,但如果我做一个虚拟等待它实际上运行得很好。问题是什么,为什么会出现?

示例代码:

import Fire2

class Test:
    def __init__(self):
        doc = asyncio.run(self.wait())

    async def wait(self):
        doc = await Fire2("test1").get(g1)  # gives the error
        # doc = await asyncio.sleep(1)  # runs without error
        return doc

    def test(self):
        x = Test2(p1)

class Test2:
    def __init__(self, p):
        doc = asyncio.run(self.run(p))
        print(doc.to_dict())

    async def run(self, p):
        doc = await Fire2('test2').get(p)
        return doc

p1 = 'foo'
g1 = 'bar'
h = Test()
h.test()

追溯:

Traceback (most recent call last):
  File "<project path>\scratch.py", line 137, in <module>
    h.test()
  File "<project path>\scratch.py", line 123, in test
    x = Test2(p1)
  File "<project path>\scratch.py", line 127, in __init__
    doc = asyncio.run(self.run(p))
  File "<user AppData>\Local\Programs\Python\Python39\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "<user AppData>\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete
    return future.result()
  File "<project path>\scratch.py", line 131, in run
    doc = await Fire2('test2').get(p)
  File "<project path>\<Fire2 file>", line 422, in get
    res = await self._collection.document(doc_id).get()
  File "<project path>\venv\lib\site-packages\google\cloud\firestore_v1\async_document.py", line 364, in get
    response_iter = await self._client._firestore_api.batch_get_documents(
  File "<project path>\venv\lib\site-packages\google\api_core\grpc_helpers_async.py", line 171, in error_remapped_callable
    call = callable_(*args, **kwargs)
  File "<project path>\venv\lib\site-packages\grpc\aio\_channel.py", line 165, in __call__
    call = UnaryStreamCall(request, deadline, metadata, credentials,
  File "<project path>\venv\lib\site-packages\grpc\aio\_call.py", line 553, in __init__
    self._send_unary_request_task = loop.create_task(
  File "<user AppData>\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 431, in create_task
    self._check_closed()
  File "<user AppData>\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
sys:1: RuntimeWarning: coroutine 'UnaryStreamCall._send_unary_request' was never awaited

Process finished with exit code 1

【问题讨论】:

  • @DivyaniYadav 不确定,但那些似乎不一样,因为我可以在一种情况下运行我的代码,但不能在另一种情况下运行
  • 发表了答案,有用吗?
  • 呃,这是一个错字,因为如果这是问题所在,脚本会崩溃。将编辑。
  • 我想它会?由于我输入了该导入语句,但其余部分直接粘贴。

标签: python python-3.x google-cloud-firestore python-asyncio


【解决方案1】:

在conftest.py中使用带有scope="session"的fixture来使用pytest

@pytest.fixture(scope="session")
def event_loop():
    loop = get_event_loop()
    yield loop
    loop.close()

【讨论】:

    【解决方案2】:

    您正在对asyncio.run 进行两次单独的调用。我们可以从stack trace 中看到错误来自grpc library 内部。我怀疑两次都使用了相同的 grpc 连接,并且在其初始化期间,它会将自身与异步事件循环集成,以便在调用之间在后台保持连接。

    问题是每次调用asyncio.run,都会创建一个新的事件循环,而每次它返回时,该事件循环都会关闭。所以当你再次调用这个函数时,grpc layer 尝试完成它的工作,它意识到原来的事件循环已经关闭并返回这个错误。

    要解决此问题,您可以对asyncio.run 进行一次调用,通常调用"main" function 或类似名称。然后,这将调用执行实际工作的 async functions

    如果问题仍然存在,那么“Fire2”类中可能存在一些问题。

    如需更多参考,您可以查看此link,其中概述了高级异步 API 以借助各种示例与协程和任务一起工作。

    【讨论】:

    • 但是,如果我只是运行一个虚拟的 await 协程(参见示例代码中的注释),它运行时没有任何错误,所以似乎问题不在于事件循环?在不同的地方调用asyncio.run 也会导致只创建一个循环吗?
    • 是否可以创建多个even_loop和firebase客户端的多个初始化?
    猜你喜欢
    • 2018-10-26
    • 2021-10-22
    • 2019-12-15
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 2022-01-20
    相关资源
    最近更新 更多