bilibili-api
bilibili-api copied to clipboard
sync函数近期更改,该如何调用?
Python 版本: 3.11.10
模块版本: 可用版本:16.1.1 报错版本:16.3.0
运行环境: Linux
我在16.1.1版本时可以这么使用sync:
sync(asyncio.gather(*[some_coroutine(), some_other_coroutine(),
refresh_credentials_loop(credential_dict=credential_dict, database=mydb)
))
更新到16.3.0之后会报错sync 22行: no running event loop
看起来16.1.1与16.3.0之间sync进行了比较大的改变。请问现在该如何正确使用呢?
我改的。当时没有测试linux环境。这个应该是sync函数的bug。能看一下具体的报错信息吗?能不能把完整的报错信息截图发出来
if __name__ == "__main__":
sync(asyncio.gather(*[roomInfos[room_id]['live_danmaku'].connect() for room_id in ROOM_IDS],
refresh_credentials_loop(credential_dict=credential_dict, database=mydb)
))
其中roomInfos[room_id]['live_danmaku'] 是一个LiveDanmaku类
报错信息为:
Traceback (most recent call last):
File "/home/ubuntu/BiliLiveManager/test/lib/python3.11/site-packages/bilibili_api/utils/sync.py", line 22, in sync
asyncio.get_running_loop()
RuntimeError: no running event loop
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/ubuntu/BiliLiveManager/master.py", line 168, in <module>
sync(asyncio.gather(*[roomInfos[room_id]['live_danmaku'].connect() for room_id in ROOM_IDS],
File "/home/ubuntu/BiliLiveManager/test/lib/python3.11/site-packages/bilibili_api/utils/sync.py", line 24, in sync
return asyncio.run(coroutine)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/runners.py", line 89, in run
raise ValueError("a coroutine was expected, got {!r}".format(coro))
ValueError: a coroutine was expected, got <_GatheringFuture pending>
sys:1: RuntimeWarning: coroutine 'refresh_credentials_loop' was never awaited
sys:1: RuntimeWarning: coroutine 'LiveDanmaku.connect' was never awaited
使用改之前的sync()版本就不会报错
不是很懂为什么会这样。理论上这行代码引发错误会被捕获。 你可以研究研究为什么。
如果只想解决问题,可以试试使用asyncio.run(coroutine)代替sync(coroutine)
def sync(coroutine: Coroutine) -> Any:
"""
同步执行异步函数,使用可参考 [同步执行异步代码](https://nemo2011.github.io/bilibili-api/#/sync-executor)
Args:
coroutine (Coroutine): 执行异步函数所创建的协程对象
Returns:
该协程对象的返回值
"""
try:
asyncio.get_running_loop()
except RuntimeError:
return asyncio.run(coroutine)
else:
with ThreadPoolExecutor() as executor:
return executor.submit(asyncio.run, coroutine).result()
很明显你自己试一下就知道,asyncio.run 不能跑 asyncio.tasks._GatheringFuture...
loop.run_until_complete 是可以的
很明显你自己试一下就知道,
asyncio.run不能跑asyncio.tasks._GatheringFuture...
loop.run_until_complete是可以的
https://github.com/Nemo2011/bilibili-api/commit/103f506c9491321f6e54d6cde64706cf3e18ccdf#diff-08987623f732733cf9ff6fc7cb33152b8a29dc805f517670957f2a1e5b60a621L33 这个修改
https://docs.python.org/zh-cn/3.13/library/asyncio-runner.html#asyncio.run
asyncio.gather 给的是 asyncio.tasks._GatheringFuture,而 asyncio.run 是不认的