【问题标题】:Why a traceback is not thrown when accessing an element in a dict that does not exist? [duplicate]为什么在访问不存在的字典中的元素时不抛出回溯? [复制]
【发布时间】:2023-04-02 15:20:01
【问题描述】:

我的代码中有一个地方,我在 dict 的键名中犯了一个错误。花了一些时间才明白为什么代码没有跑过那个地方因为没有抛出回溯

代码如下,为了完整起见,我把它放在→→→突出问题的地方:

class Alert:

    lock = threading.Lock()
    sent_alerts = {}

    @staticmethod
    def start_alert_listener():
        # load existing alerts to keep persistancy
        try:
            with open("sent_alerts.json") as f:
                json.load(f)
        except FileNotFoundError:
            # there is no file, never mind - it will be created at some point
            pass
        # start the listener
        log.info("starting alert listener")
        client = paho.mqtt.client.Client()
        client.on_connect = Alert.mqtt_connection_alert
        client.on_message = Alert.alert
        client.connect("mqtt.XXXX", 1883, 60)
        client.loop_forever()

    @staticmethod
    def mqtt_connection_alert(client, userdata, flags, rc):
        if rc:
            log.critical(f"error connecting to MQTT: {rc}")
            sys.exit()
        topic = "monitor/+/state"
        client.subscribe(topic)
        log.info(f"subscribed alert to {topic}")

    @staticmethod
    def alert(client, userdata, msg):
        event = json.loads(msg.payload)
        log.debug(f"received alert: {event}")
→→→     if event['ok']:
            # remove existing sent flag, not thread safe!
            with Alert.lock:
                Alert.sent_alerts.pop(msg['id'], None)
            return
        (...)
        

来自上一行的日志是

2021-01-14 22:03:02,617 [monitor] DEBUG received alert: {'full_target_name': 'ThisAlwaysFails → a failure', 'isOK': False, 'why': 'explicit fail', 'extra': None, 'id': '6507a61c9688199a34cb006b354c8433', 'last': '2021-01-14T22:03:02.612912+01:00', 'last_ko': '2021-01-14T22:03:02.612912+01:00'}

这是我试图错误访问okdict,它应该引发异常和回溯。但什么也没有发生。代码并没有更进一步,就好像错误被无声地丢弃(并且该方法无声地失败)。

我试图在 log.debug()if 之间放置一个 raise Exception("wazaa") - 同样的,该方法在此时失败,但没有引发异常。

我不知道为什么通过回溯无法看到异常?


alert() 方法在单独的线程中调用,如果这很重要的话。为了完整起见,我尝试了以下代码以确保 threading 不会干扰但不会(我看不出它应该这样做的原因)

import threading

class Hello:

    @staticmethod
    def a():
        raise Exception("I am an exception")

threading.Thread(target=Hello.a).start()

输出

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Python38\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:/Users/yop/AppData/Roaming/JetBrains/PyCharm2020.3/scratches/scratch_1.py", line 7, in a
    raise Exception("I am an exception")
Exception: I am an exception

【问题讨论】:

  • 好像错误被默默丢弃了,你可以放一个print看看是不是这样。
  • @Countour-Integral:我不明白。不是日志没有显示,而是 Traceback
  • 我不知道paho 是什么,但我猜它是在try 内部执行client.on_messageclient 对象可能包含捕获的错误列表?
  • @WoJ 是的,但是if event['ok'] 会发生什么,我说你可以在 if 里面放一个 print,在外面放一个,看看函数是否被“杀死”。你也可以尝试raiseing 你自己的异常,看看会发生什么。
  • 调用alert 的东西可能会捕获并抑制异常。由于我们不知道这个on_message 是什么,也不知道它是如何工作的,所以很难说。如果event 中没有“ok”键,则会引发异常,并且可能有什么东西正在捕获它。

标签: python python-3.x exception


【解决方案1】:

It appears to call your callback within a try,然后记录该错误:

try:
    self.on_message(self, self._userdata, message)
except Exception as err:
    self._easy_log(
        MQTT_LOG_ERR, 'Caught exception in on_message: %s', err)
    if not self.suppress_exceptions:
        raise

但我无法解释的是为什么异常不是raised。我不明白为什么 self.suppress_exceptions 对你来说是正确的,因为你从来没有设置它,但是试试:

  • 使用client.suppress_exceptions = False 手动设置suppress_exceptions。这应该不是必需的,因为这似乎是默认设置,但值得一试。

  • 检查它显然维护的日志。你需要参考文档来了解如何做到这一点,因为我以前从未接触过这个库。

【讨论】:

  • 谢谢。我还在该路径之后发现了一个重复项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-28
  • 1970-01-01
  • 2021-02-20
  • 2017-08-21
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
相关资源
最近更新 更多