gpt4 book ai didi

python - python aiohttp socketio 中是否可能存在竞争条件?

转载 作者:行者123 更新时间:2023-12-01 00:32:35 26 4
gpt4 key购买 nike

我正在编写类似于以下代码的代码。有时程序会停止工作,或者我会收到有关 socketio session 访问的奇怪错误。慢慢地我觉得这可能是竞争条件。

更多的是伪代码。我想证明,我从多个协程访问全局共享状态和套接字 session 。

import asyncio as aio
from aiohttp import web
import socketio


app = web.Application()
sio = socketio.AsyncServer()

app["sockets"] = []

@sio.on("connect")
async def connect(sid):
app["sockets"].append(sid)

@sio.on("disconnect")
async def disconnect(sid):
app["sockets"].remove(sid)

@sio.on("set session")
async def set_session(sid, arg):
await sio.save_session(sid, {"arg": arg})

async def session_route(req):
data = await req.json()
for sid in app["sockets"]:
await sio.save_session(sid, {"arg": data["arg"]})
return web.Response(status=200)

if __name__ == '__main__':
web.run_app(app)

最佳答案

这里肯定有问题:

for sid in app["sockets"]:  # you are iterating over a list here
await sio.save_session(...) # your coroutine will yield here

您正在迭代列表app["sockets"],并且在每次迭代中使用await关键字。使用 await 关键字时,您的协程将被挂起,并且事件循环会检查另一个协程是否可以执行或恢复。

假设 connect(...) 协程在 session_route 等待时运行。

app["sockets"].append(sid)  # this changed the structure of the list

connect(...) 更改了列表的结构。这可以使该列表当前存在的所有迭代器无效。 disconnect(...) 协程也是如此。

因此,要么不要修改列表,要么至少在列表更改后不要重用迭代器。后一种解决方案在这里更容易实现:

for sid in list(app["sockets"]):
await sio.save_session(...)

现在 for 循环迭代原始列表的副本。现在更改列表不会“干扰”副本。

但请注意,副本无法识别列表中的添加和删除。

所以,简而言之,你的问题的答案是,但它与async io无关。同样的问题很容易出现在同步代码中:

for i in my_list:
my_list.remove(1) # don't do this

关于python - python aiohttp socketio 中是否可能存在竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58056397/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com