【问题标题】:I'm not sure why im getting this async error in python我不确定为什么我在 python 中得到这个异步错误
【发布时间】:2021-05-14 23:57:55
【问题描述】:

我设法让我的 api 请求异步,但在尝试将其实施到主项目时收到此错误。这意味着我做错了什么?

错误

Exception has occurred: SynchronousOnlyOperation
You cannot call this from an async context - use a thread or sync_to_async.
  File "C:\Users\Admin\Desktop\djangoProjects\dguac\Signal.py", line 124, in main
    await asyncio.wait([sigBuy(count) for count, bot in enumerate(activeBots)])
  File "C:\Users\Admin\Desktop\djangoProjects\dguac\Signal.py", line 126, in <module>
    loop.run_until_complete(main())

我不明白这个错误是什么意思以及如何解决它。

这是我的代码

async def sigBuy(count):

            bot_dict = Bot.to_dict(activeBots[count])
            sigSettings_dict = Bot.to_dict(activeBots[count].sigSettings)

            # Binance API and Secret Keys
            Bclient = CryptoXLib.create_binance_client(sigSettings_dict['API_key'], sigSettings_dict['API_secret_key'])
            
            p = round(float(percentage(7, bot_dict['ct_balance']) / (float(bin_asset_price['price']) / 1)), 8)
            # Round and Asign the asset_amount
            asset_amount = round(p, 2)

            # shouldILog = await makeBuy(market, asset_amount, Bclient, sigSettings_dict['base_currency'])
            shouldILog = 2
            if shouldILog == 2:
                asset_amount = int(asset_amount)

            last_trade = await Bclient.get_all_orders(pair = Pair(market, sigSettings_dict['base_currency']))
            last_trade = last_trade['response'][-1]
            print(last_trade)

            # asset_price = float(last_trade['cummulativeQuoteQty']) / float(last_trade['executedQty'])
            asset_price = 0.00000123
            buyInPrice = float(last_trade['cummulativeQuoteQty'])

            for otrade in activeBots[count].opentrades.all():
                trade = Bot.to_dict(otrade)
                del trade['id']
                otradesUpdate.append(trade)
            
            openTrades_dict = {'bot_ID': bot_dict['id'], 'date': date, 'market': market, 'trade_mode': 'Buy', 'price': asset_price, 'amount': asset_amount, 'amount_in_base_currency': buyInPrice, 'result': 0}

            otradesUpdate.append(openTrades_dict)
            BotsUpdate.append(bot_dict)
            SigSettingsUpdate.append(sigSettings_dict)

            await Bclient.close()


        async def main():
            await asyncio.wait([sigBuy(count) for count, bot in enumerate(activeBots)])
        
        loop.run_until_complete(main())

【问题讨论】:

    标签: python django asynchronous python-asyncio


    【解决方案1】:

    await asyncio.wait 似乎是正确的,因为您可以拥有一个可迭代的列表(即使 asyncio.wait 应该被弃用 iirc)但异常消息有点让我失望。 OP 应该做的是包装 Django ORM 的查询集并让它执行,但是 Django 的 ORM 延迟加载可能会导致一些问题。


    错误的原始答案

    你不是在等待正确的事情。你的意思是等待 sigBuy 但你的 asyncio.wait 正在等待。与此同时,您现在有了一个未执行任何操作的协程列表。

    我建议你尝试两件事:

    • 如果您想同时运行,请保留该列表但不要等待它。相反,使用 asyncio.gather 同时运行它们。 asyncio.gather([sigBuy(count) for count, bot in enumerate(activeBots)])
    • 如果您想一次运行一个,请确保列表解析的工作方式相同:[await sigBuy(count) for count, bot in enumerate(activeBots)]

    【讨论】:

    • 当我尝试使用时收到此错误,发生异常:TypeError unhashable type: 'list' File "FILEPATH", line 151, in asyncio.gather([sigBuy(count ) 用于计数,bot in enumerate(activeBots)])
    【解决方案2】:

    我通过使用解决了这个错误

        async def main():
            await asyncio.wait([sigBuy(count) for count, bot in enumerate(activeBots)])
    
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(main())
    

    还首先将过滤和预取的 django 查询中的每个项目附加到新的 activeBots 列表中,以便异步代码接受它。

    【讨论】:

    • 啊,我应该从异常消息中意识到这是 Django。您可以做的是导入 asgiref.sync_to_async 并将您的查询集包装在其中,例如 sync_to_async(qs)()
    猜你喜欢
    • 1970-01-01
    • 2016-11-25
    • 1970-01-01
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多