我有一个 python 应用程序,它使用线程从 MQTT 代理接收主题,并监视 UART 上的消息。在 Raspberry Pi 上运行。
泛美卫生组织 MQTT 库的接口提供回调来处理接收消息,并且
loop_start()
显然启动了一个新线程然后返回。
我的问题是,我希望接收回调中可能出现的异常一直引发到应用程序的“顶部”,以便我可以干净地终止整个应用程序。
现在,泛美卫生组织线程中的异常会终止该线程,但其他线程仍保持活动状态,并且应用程序正在运行但无法运行。这很糟糕,我依靠 systemd 服务来重新启动崩溃的应用程序,这就是为什么我需要它真正崩溃。
我已经为 UART RX 线程完成了此操作:
class MyClassError(Exception):
def __init__(self, message):
self.message = f"{message}"
super().__init__(self.message)
class MyClass()::
# other stuff...
def rx(self):
try:
while True:
do_your_thing()
except Exception as e:
self.exc = MyClassError(f"An unexpected error occurred: {e}")
return
def run(self):
self.rx_thread.start()
self.rx_thread.join()
if self.exc is not None:
raise self.exc
,它有效,但有一个警告,它不会返回。但我可以在调用者线程中捕获异常。
还有其他方法可以实现类似的效果,例如回调代码中的
try
/except
/sys.exit(1)
,或者也许让主线程监视paho线程的状态......但感觉我应该能够在子线程中引发异常,并在父线程中捕获它们。
此外,我想捕获并引发任何 MQTT 代码中的任何异常,而不仅仅是特定的回调。但这是第 2 步。
如何将 paho 库(或其调用的回调)中发生的异常升级到主线程,以便它可以终止一切?
我当前的解决方案是通过这种方式在顶层捕获未捕获的异常:
def handle_exceptions(e):
try:
my_object.stop()
except Exception as e:
print(e)
try:
mqtt_manager.stop()
except Exception as e:
print(e)
print(traceback.print_exception(e.exc_type, e.exc_value, e.exc_traceback))
threading.excepthook = handle_exceptions
MQTT 循环在此停止后需要几秒钟才能终止(我想知道为什么?循环是否仅在下一个事件时终止?),但整个应用程序最终终止。