python-asyncio TypeError:对象字典不能用于“等待”表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49822552/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 19:15:32  来源:igfitidea点击:

python-asyncio TypeError: object dict can't be used in 'await' expression

pythonpython-asyncio

提问by Riley Hughes

I am using a third party module to retrieve data from an API. I simply would like to asynchronously await the module to return the data which occasionally takes several seconds and freezes up my app. However, when I try to await a call to that module I receive the TypeError:

我正在使用第三方模块从 API 检索数据。我只是想异步等待模块返回有时需要几秒钟并冻结我的应用程序的数据。但是,当我尝试等待对该模块的调用时,我收到了 TypeError:

TypeError: object dict can't be used in 'await' expression

TypeError: object dict can't be used in 'await' expression

import thirdPartyAPIwrapper

async def getData():
    retrienveData = await thirdPartyAPIWrapper.data()
    return await retrieveData

def main():
    loop = asncio.get_event_loop()
    data = loop.run_until_complete(getData())
    loop.close
    return data

Why can I not await a type('dict')? Is there a way around this? If async/await with asyncio will not work with a third party module that doesn't return a coroutine then what are my other options?

为什么我不能等待类型('dict')?有没有解决的办法?如果 async/await 与 asyncio 不适用于不返回协程的第三方模块,那么我的其他选择是什么?

回答by Mikhail Gerasimov

Only asynchronous (defined with async def) functions can be awaited. Whole idea is that such functions are written special way what makes possible to run (await) them without blocking event loop.

只能async def等待异步(用 定义)函数。整个想法是,这样的函数是用特殊的方式编写的,可以在await不阻塞事件循环的情况下运行()它们。

If you want to get result from common (defined with def) function that takes some considerable time to be executed you have these options:

如果您想从def需要相当长的时间来执行的common(用 定义)函数获得结果,您可以使用以下选项:

  • rewrite this whole function to be asynchronous
  • call this function in another thread and await for result asynchronously
  • call this function in another process and await for result asynchronously
  • 将整个函数重写为异步
  • 在另一个线程中调用此函数并异步等待结果
  • 在另一个进程中调用此函数并异步等待结果

Usually you want to choose second option.

通常你想选择第二个选项。

Here's example of how to do it:

以下是如何执行此操作的示例:

import asyncio
import time
from concurrent.futures import ThreadPoolExecutor


_executor = ThreadPoolExecutor(1)


def sync_blocking():
    time.sleep(2)


async def hello_world():
    # run blocking function in another thread,
    # and wait for it's result:
    await loop.run_in_executor(_executor, sync_blocking)


loop = asyncio.get_event_loop()
loop.run_until_complete(hello_world())
loop.close()

Please, read this answerabout how asyncio works. I think it'll help you much.

请阅读有关 asyncio 如何工作的答案。我想它会对你有很大帮助。

回答by Serge

As thirdPartyAPIWrapper.data()is a normal sync function you should call it in another thread.

作为thirdPartyAPIWrapper.data()一个普通的同步函数,你应该在另一个线程中调用它。

There is a helper function for that in a asgireflibrary.
Assume we've got a blocking function with an argument:

库中有一个辅助函数asgiref
假设我们有一个带参数的阻塞函数:

import asyncio
import time

from asgiref.sync import sync_to_async


def blocking_function(seconds: int) -> str:
    time.sleep(seconds)
    return f"Finished in {seconds} seconds"

async def main():
    seconds_to_sleep = 5
    function_message = await sync_to_async(blocking_function)(seconds_to_sleep)
    print(function_message)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

There is also an async_to_synchelper function in that library.

async_to_sync该库中还有一个辅助函数。

回答by Souradeep Nanda

I am writing test cases and I need to mock async functionality. So, you can write a simple helper function like so.

我正在编写测试用例,我需要模拟异步功能。因此,您可以像这样编写一个简单的辅助函数。

async def resolve(val):
    return val

Now you can await anything

现在你可以等待任何事情

foo = resolve(1) 
await foo # No error!