python 为什么我一直得到错误“TypeError object dict_keys can't be used in 'await' expression”

icnyk63a  于 2023-06-04  发布在  Python
关注(0)|答案(2)|浏览(221)

我正在尝试基于来自GitHub here的一段工作良好的代码来创建一个小型异步应用程序。我试着把它稍微修改一下,以适应我这样的需要

  • main.py*
import asyncio
from kernel.init import Init
async def main():
    init = Init()
    await init.loadSymbols()
if __name__ == '__main__':
    loop = asyncio.new_event_loop()
    asyncio.run(main())
  • init.py*
import ccxt.async_support as ccxt

class Init:
    async def loadSymbols(self):
        symbols_list = {}
        for exchange_id in ['poloniex', 'binance']:
            exchange_class = getattr(ccxt, exchange_id)
            exchange = exchange_class()
            try:
                await exchange.load_markets()
                symbols_list[exchange_id] = await exchange.markets.keys()
            except Exception as e:
                print(type(e).__name__, str(e))
            await exchange.close()
        return symbols_list

但是当我开始的时候,我得到这个错误
TypeError对象dict_keys不能用于'await'表达式
当然,我在谷歌上搜索了很长时间,基于互联网上类似的例子(link 1link 2),我试图修复我的代码。* 尝试一次 *

class Init:
    async def loadSymbols(self):
        symbols_list = {}
        for exchange_id in ['poloniex', 'binance']:
            exchange_class = getattr(ccxt, exchange_id)
            exchange = exchange_class()
            try:
                await exchange.load_markets()
                input_coroutines = exchange.markets.keys()
                symbols_list = await asyncio.gather(*input_coroutines, return_exceptions=True)
            except Exception as e:
                print(type(e).__name__, str(e))
            await exchange.close()
        return symbols_list

但在这种情况下我得到一个错误
TypeError需要asyncio.Future、协程或awaitable

  • 第二次尝试 *
input_coroutines = [list(exchange.markets.keys())[0]]

我使用了几乎所有的技巧,我发现在互联网上类似的问题(我不会写在下面,使问题看起来不太大),但是,没有一个不为我工作。请你告诉我如何摆脱这个错误-我已经完全放弃了

ivqmmu1c

ivqmmu1c1#

这是完全正确的,exchange.markets.keys()看起来是一组普通的dict键,而不是由协程填充的东西。尝试完全删除它:symbols_list[exchange_id] = exchange.markets.keys()
调试时,我看到exchange.markets.keys()包含一组正常的字典键:dict_keys(['BTS/BTC', ..., 'WFAI/USDT'])。如果它是一个协程,它会说:<coroutine object dict_keys at ...>
你永远不需要这样做,但为了帮助你理解:如果你想把一个普通的函数变成一个异步函数,你可以 Package 它:

import asyncio
def fn(x):
    return x + 1

async def fn_def(x):
    return x+1

def deferrer(some_fn):
    async def deferred(*args, **kwargs):
        return fn(*args, **kwargs)
    return deferred

deferred_fn = deferrer(fn)

print(fn(3))
print(asyncio.run(fn_def(3)))
print(asyncio.run(deferred_fn(3)))
ulmd4ohb

ulmd4ohb2#

你可以尝试删除后等待前exchange.markets.kesy()喜欢

import ccxt.async_support as ccxt

class Init:
    async def loadSymbols(self):
        symbols_list = {}
        for exchange_id in ['poloniex', 'binance']:
            exchange_class = getattr(ccxt, exchange_id)
            exchange = exchange_class()
            try:
                await exchange.load_markets()
                symbols_list[exchange_id] = exchange.markets.keys()
            except Exception as e:
                print(type(e).__name__, str(e))
            await exchange.close()
        return symbols_list

因为我在源代码中看到self.markets是一个简单的字典

#https://github.com/ccxt/ccxt/blob/master/python/ccxt/async_support/base/exchange.py#L705

def set_markets(self, markets, currencies=None):
    values = []
    self.markets_by_id = {}
    # handle marketId conflicts
    # we insert spot markets first
    marketValues = self.sort_by(self.to_array(markets), 'spot', True)
    for i in range(0, len(marketValues)):
        value = marketValues[i]
        if value['id'] in self.markets_by_id:
            (self.markets_by_id[value['id']]).append(value)
        else:
            self.markets_by_id[value['id']] = [value]
        market = self.deep_extend(self.safe_market(), {
            'precision': self.precision,
            'limits': self.limits,
        }, self.fees['trading'], value)
        values.append(market)
    self.markets = self.index_by(values, 'symbol')

相关问题