Aiohttp / 阻塞send_str方法

问题描述 投票:0回答:1

我对 asyncio 和 aiohttp 有一点理解问题。

看看我的代码,我期望得到以下结果:Asyncio Gather() 首先从 funk1 开始。打印“a”并将购买订单发送到 okx 加密货币交易所。在await okxprivatsocket.send_str之后,控制权被放弃,代码跳转到funk2()。现在“c”已打印出来。最后,当await okxprivatsocket.send_str完成时,将打印“b”。

如果我现在运行代码,我会得到以下输出:a、b、c。这正是我不明白的地方。看起来好像“await okxprivatsocket.send_str”等待结果,然后才转到 funk2。我理解asyncio的方式是在await关键字之后放弃控制。我有什么误解吗?

我将非常感谢您的解释性答案, 问候,安德烈亚斯

这是我的代码:


import time
import aiohttp
import asyncio
import okx.websocket.WsUtils as wub



async def main():
    
    apiKey = "XXXXXXXXXXXX" 
    passphrase = "XXXXXXXXXXX"
    secretKey = "XXXXXXXXXXXXXXXXXX"  
    
    okxprivat_url = "wss://wsaws.okx.com:8443/ws/v5/private"
    loginparamstr = wub.initLoginParams(time.time, apiKey, passphrase, secretKey)
    okxprivat_message = '{"op":"subscribe","args":[{"channel":"orders","instType":"SPOT","instId":"KDA-USDT"}]}'   
    
    session = aiohttp.ClientSession()
        
    async with session.ws_connect(okxprivat_url) as okxprivatsocket :
    
     await okxprivatsocket.send_str(loginparamstr)
     await asyncio.sleep(1)
     await okxprivatsocket.send_str(okxprivat_message)
    
     await asyncio.gather(funk1(okxprivatsocket),funk2())
    
            
        
async def funk1(okxprivatsocket):
    
      print("a")
          
      await okxprivatsocket.send_str('{"id":"33321","op": "order","args":[{"side": "buy","instId": "KDA-          USDT","tdMode": "cash","ordType": "limit","px": 1, "sz": 10}]}')
      
      print("b")
      
async def funk2():
    
      print("c")
      

if __name__ == '__main__':
    asyncio.run(main())



websocket python-asyncio aiohttp
1个回答
0
投票

我理解asyncio的方式是在await关键字之后放弃控制。我有什么误解吗?

await
(和
async for/with
)是您的代码可能屈服于事件循环的唯一地方。这可以通过 funk2() 函数轻松显示。该函数中的代码显然不会屈服于事件循环,因此等待它永远不会屈服于事件循环:

await funk2()
await funk2()
await funk2()

此代码永远不会产生结果,并且在功能上与同步函数相同。

send_str()没有yield的原因可能是因为数据很小,并且套接字已打开并准备就绪,因此它能够将所有数据无延迟地推送到套接字缓冲区并完成,而无需等待任何IO。我怀疑如果您通过同一个套接字发送较大的请求或大量请求,您会发现缓冲区已满,然后在等待套接字准备好接收更多数据时会进入循环。

如果您需要确保代码在某个时刻屈服,以确保它不会阻塞太长时间,那么您可以使用

await asyncio.sleep(0)
,这将屈服于事件循环进行 1 次迭代。

© www.soinside.com 2019 - 2024. All rights reserved.