larksuite / larksuite/oapi-sdk-python
[Python lark-oapi 1.6.7] ws/client.py module-level event loop causes RuntimeError when first imported inside a running loop
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 559
- Forks
- 102
- PR merge metrics
- No merged PRs in 30d
Description
Environment
- Package:
lark-oapi1.6.7 (Python) - Python: 3.9+
- Affected path:
lark_oapi/ws/client.py
Summary
lark_oapi/ws/client.py captures the event loop at module import time via a module-level global. If the module is first imported while an event loop is already running (e.g. inside asyncio.run()), the subsequent loop.run_until_complete(...) raises RuntimeError: This event loop is already running, and the WebSocket long-connection fails immediately.
Root Cause
client.py lines 30-34 run at import time:
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
Under Python 3.9, asyncio.get_event_loop() returns the currently running loop when called from within a coroutine / asyncio.run() context, so the module-level loop captures an already-running loop.
client.py then uses this global in start():
# client.py:163, 169, 171, 176
loop.run_until_complete(self._connect())
...
loop.run_until_complete(_select())
Calling run_until_complete on an already-running loop raises RuntimeError: This event loop is already running.
Reproduction
import asyncio
async def main():
from lark_oapi.ws.client import Client # first import here captures the running loop
Client(...).start() # RuntimeError: This event loop is already running
asyncio.run(main())
Real-world Trigger
Host applications that lazily import lark_oapi.channel (which transitively imports lark_oapi.ws.client) from within their asyncio main loop hit this unconditionally on first startup.
Suggested Fix
Remove the module-level loop global; create a dedicated event loop per Client instance inside the worker thread in start(), isolating the WS client from the caller's event loop.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with lark_oapi/ws/client.py, especially the module-level loop setup at lines 30-34 and the run_until_complete calls around lines 163, 169, 171, and 176. Run the provided asyncio.run reproduction, then trace Client.start() and its worker-thread behavior. Done means the client can be first imported and started inside a running asyncio loop without the RuntimeError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100