【问题标题】:Difference between raising exception and automatically causing an exception引发异常和自动引发异常的区别
【发布时间】:2014-06-18 00:36:43
【问题描述】:

目前使用wxPython框架,我的代码如下:

事件绑定:

self.frequency_grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_changed)

处理更改单元格的函数:

def on_cell_changed(self, event):
    self.current_grid = event.GetEventObject()
    try:
        new_value= self.get_cell_value()
        if new_value < 0:
            raise AttributeError
        #allow the cell to update
    except AttributeError:
        event.Veto()
        wx.MessageBox(_("Positive values only."), "", wx.OK|wx.ICON_WARNING)
    except:
        wx.MessageBox(_("Invalid value for cell."), "", wx.OK|wx.ICON_WARNING)
        event.Veto()

get_cell_value() 函数从当前单元格中读取值,并简单地使用 int() 将其转换为整数。如果用户在单元格中输入像“a”这样的字符,显然这个函数会失败并引发异常。在这种情况下,消息框会告诉用户单元格的值无效。这就是我所说的自动引发的异常,执行最后的异常块。

在负值的情况下,我手动引发了一个 AttributeError(只是想看看与 ValueError 不同的东西,这是用户输入字符时发生的情况)。 然而,在这种情况下,wxPython 会发送两次 EVT_GRID_CELL_CHANGE 事件,因此手动引发的异常肯定有所不同。

我已经在http://trac.wxwidgets.org/ticket/16333 单独提出了关于重复事件的票证,但只是想了解第一个场景与第二个场景相比如何不会使 wxPython 发送 2 个事件。

【问题讨论】:

    标签: python wxpython


    【解决方案1】:

    如果您真的想捕获任何可能的错误(甚至是系统内存或其他任何不相关的错误),请不要使用except:

    为了让您的代码看起来更好,我建议使用 try...except 块将 value 转换为 int,然后检查负值。

    try:
        value = int(text)
    except:
        return MessageBox('Enter digit')
    if value < 0:
        return MessageBox('Enter positive digit')
    

    【讨论】:

    • 这就是 try 语句的作用,如果我从 try 块调用另一个函数并在该函数中使用 int(text) 或直接执行 int()在同一个 try 块内。
    【解决方案2】:

    Exceptions 没有区别,但是您在代码中的不同位置以不同的方式处理它们。

    我怀疑是 veto() 调用导致了额外的事件。但是为什么不只在一个地方验证输入呢?即你的 get_cell_value() 函数应该确保它是一个整数 >0。

    此外,这种结构既是循环事件的秘诀,也是令人痛苦的烦人 UI。人们应该能够打错字并返回并更正它,而不会弹出烦人的对话框。

    也许提供问题的指示,例如将单元格背景设置为红色,但只有在用户尝试继续下一步时才进入对话路径。

    【讨论】:

    • 否决权不会导致额外事件。如果我不使用消息框,则事件不会以某种方式重复。我如何以不同的方式处理异常?如果异常没有区别,那么我引发异常并且代码从无效的 int() 转换自动触发异常应该导致两个异常处理类似。您可能在一个地方对 UI 设计或验证是正确的,但我最初的问题是首先要问为什么会发生这种特殊情况。
    【解决方案3】:

    经过更多跟踪,我发现创建 MessageBox 会导致 EVT_GRID_CELL_CHANGING 事件发生,然后导致 EVT_GRID_CELL_CHANGED 事件发生,这就是我看到重复事件的原因。 在输入字符期间我没有看到重复事件的原因是因为如果 int() 转换无效,则在 EVT_GRID_CELL_CHANGING 的事件处理程序中调用了 Veto(),因为我的该事件的处理程序获取了网格输入并尝试转换它。

    综上所述,Python异常处理没有区别,但是,应该实现一个更好的wxPython demo,防止demo过程中出现重复的消息框,向其他用户展示如何更好地使用网格机制。

    【讨论】:

      猜你喜欢
      • 2023-03-29
      • 1970-01-01
      • 2014-10-25
      • 2012-02-11
      • 2010-09-08
      • 2014-08-31
      • 2016-08-31
      • 2013-08-02
      • 2012-10-10
      相关资源
      最近更新 更多