Python中如何在外部作用域捕获Firestore on_snapshot的错误?
如何捕获Firestore on_snapshot回调中的错误
你的程序通过外层try-except捕获main函数的错误实现重启,但Firestore的on_snapshot回调运行在独立的后台执行上下文,错误无法被外层的try-except捕获。以下是几种可行的解决方式:
方法1:在回调内部捕获错误并抛入主事件循环
在collection_changed内部先捕获错误,再通过asyncioAPI将错误传递到主事件循环,让外层逻辑能捕获到:
import asyncio def collection_changed(docs, changes, time): try: # 原业务逻辑 raise RuntimeError("Something wrong.") except Exception as e: # 获取当前运行的事件循环 loop = asyncio.get_running_loop() # 线程安全地将错误抛入事件循环,触发异常处理 loop.call_soon_threadsafe( lambda: loop.call_exception_handler({ "message": "Snapshot callback error occurred", "exception": e }) ) # 停止事件循环,让外层main_loop触发重启 loop.call_soon_threadsafe(loop.stop) async def main(): col_ref.on_snapshot(collection_changed) await some_forever_task()
方法2:用异步队列传递错误到主任务
创建异步队列,在回调中把错误存入队列,主任务里监听队列,收到错误后主动抛出,让外层try-except捕获:
import asyncio error_queue = asyncio.Queue() def collection_changed(docs, changes, time): try: # 原业务逻辑 raise RuntimeError("Something wrong.") except Exception as e: loop = asyncio.get_running_loop() # 线程安全地将错误放入队列 loop.call_soon_threadsafe(error_queue.put_nowait, e) async def listen_for_errors(): while True: error = await error_queue.get() # 抛出错误,触发外层捕获逻辑 raise error async def main(): col_ref.on_snapshot(collection_changed) # 同时运行原永久任务和错误监听任务 await asyncio.gather(some_forever_task(), listen_for_errors())
方法3:使用Firestore的错误回调参数
Firestore的on_snapshot支持传入error_callback参数,专门处理监听过程(包括回调执行)中的错误,可直接在这里触发重启逻辑:
def handle_snapshot_error(error): # 执行停止和重置逻辑(注意线程安全) stop_everything() reset_everything() # 停止事件循环,让main_loop进入重启流程 loop = asyncio.get_running_loop() loop.call_soon_threadsafe(loop.stop) async def main(): # 绑定快照回调和错误回调 col_ref.on_snapshot(collection_changed, error_callback=handle_snapshot_error) await some_forever_task()
内容的提问来源于stack exchange,提问作者Jeffrey Chen
相关产品推荐
相关产品推荐

