ws.Client: module-level loop variable prevents multiple instances (multi-bot race condition)
還沒有人認領這個 Issue。
評估
研究方向
從 lark_oapi/ws/client.py 第 26-29 行附近的模組層級迴圈開始,接著追蹤第 171 行的 Client.start() 和 _receive_message_loop。重現 issue 中描述的多個 bot 分別執行於不同 thread 的情況,並判斷預期採用以 instance 或 async API 為基礎的方式。完成標準是:彼此獨立的 ws.Client instance 不再共用或覆寫 event loop,並且可以並行執行而不會出現回報的 RuntimeError。
由索引模型根據 Issue 內容生成。
描述
Problem
lark_oapi/ws/client.py uses a module-level loop variable (line 26-29):
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
All ws.Client instances share this single loop reference. When multiple Feishu bots are started in separate threads (a common pattern for multi-bot applications), they overwrite each other's loop, causing RuntimeError: This event loop is already running.
Race condition
- Thread A:
ws_mod.loop = loop_A - Thread B:
ws_mod.loop = loop_B(overwrites A) - Thread A:
cli.start()→ readsws_mod.loop→ getsloop_B→loop_B.run_until_complete() - Thread B:
cli.start()→ readsws_mod.loop→ getsloop_B→ ERROR: already running
Even after connecting, _receive_message_loop (line 171) uses loop.create_task() which may reference the wrong loop.
Current workaround
We replaced ws_mod.loop with a thread-local proxy:
class _ThreadLocalLoopProxy:
def __getattr__(self, name):
return getattr(asyncio.get_event_loop(), name)
ws_mod.loop = _ThreadLocalLoopProxy()
This works but is fragile against SDK changes.
Suggested fix
Make ws.Client instance-based, like the Node.js SDK (@larksuiteoapi/node-sdk) already does with WSClient:
class Client:
def __init__(self, ...):
self._loop = asyncio.new_event_loop()
...
def start(self):
self._loop.run_until_complete(self._connect())
self._loop.create_task(self._ping_loop())
self._loop.run_until_complete(_select())
Or provide an async start_async() method (as suggested in #96) so the client can integrate with existing event loops (e.g., uvicorn, FastAPI).
Related issues
- #96 —
loopconflicts with async frameworks - #109 — concerns about production readiness
Environment
- lark_oapi version: latest (PyPI)
- Python: 3.13
- Use case: multi-bot IM middleware (each bot = separate
ws.Clientinstance in its own thread)
- 主要語言
- Python
- 星號
- 560
- 分支
- 102
- PR 合併指標
- 30 天內沒有已合併 PR
環境準備
這個專案沒有提供開發容器、Dockerfile 或貢獻指南,環境需要你自己搭建:先看它的 README,通用步驟見我們的新手貢獻指南。
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
larksuite/oapi-sdk-python 的其他 Issue
-
難度 2/5 1-3 小時 新手友好度 67/100
larksuite/oapi-sdk-python#163 · 1 則留言 ·
-
難度 2/5 1-3 小時 新手友好度 82/100
larksuite/oapi-sdk-python#162 · 1 則留言 ·
-
難度 1/5 1 小時以內 新手友好度 94/100
larksuite/oapi-sdk-python#161 ·
-
難度 1/5 1 小時以內 新手友好度 90/100
larksuite/oapi-sdk-python#160 ·
-
難度 2/5 1-3 小時 新手友好度 78/100
larksuite/oapi-sdk-python#159 ·
查看 larksuite/oapi-sdk-python 的全部 Issue
相似的 Issue
-
bug server
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 78/100
sportsdataverse/sportsdataverse-py#641 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 82/100
googleapis/google-cloud-python#18532 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 72/100
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 72/100
維護者通常 1 天內回覆