【问题标题】:Make python don't undo things after an error is raised in try block在 try 块中引发错误后,使 python 不撤消操作
【发布时间】:2020-11-13 10:24:14
【问题描述】:

我有一个 python 类,我可以在其中打开文件并读出数据。如果不满足某些条件,我会引发一个错误,但在此之前我通过为对象指定一个属性来指定错误:self.Error = specification。但是由于引发错误会撤消 try 块中的所有内容,因此我无法访问它。这发生在__init__ 函数中,因此创建的对象甚至不存在..

这是必要的代码:

class MyClass:
    def __init__(self):
        #do something
        if this_or_that:
            self.Error = specification
            raise MyCostumError
try:
    object = MyClass()
except MyCostumError:
    print(object.Error)

我得到:NameError: name 'object' is not defined

只是为了澄清: 我已经定义了MyCostumError,变量名只是为了更好地理解:我使用好的变量名,它们已定义,我需要澄清,因为可以在不同的行中引发错误。

所以这是我的问题: 有没有类似try/except 的东西,但是当出现错误时,它不会撤消所有操作。还是我只是愚蠢,有一种更简单的方法可以实现这一目标?

【问题讨论】:

  • 为什么不想把错误“规范”放入错误中?
  • 这是我第一次尝试引发错误。我不知道这是可能的。

标签: python python-3.x class error-handling try-catch


【解决方案1】:

您正试图引用一个不存在的对象。让我解释: 如果在尝试初始化对象时发生错误,则不会初始化该对象。所以如果你尝试在它没有初始化的时候加入它,你会得到一个错误。

try:
    object = MyClass() #initialising object successful, object existing.
except: #initialising failed, object does not exist.
    print(object.Error) #nameError, since object was never created.

Try/except 不会撤消任何操作,只是在发生错误时停止做某事。

【讨论】:

  • 如果“从未创建对象”,那么为什么self.Error 不创建不同的错误?显然self 已经被创建了。
  • 正确的表述方式是MyClass() 引发异常以便object = 分配永远不会发生
  • 好吧,函数中产生错误的所有内容都将被撤消。
  • 感谢您的解释
  • 所以如果打印了某些东西,它就不会打印了?
【解决方案2】:

引发错误不会撤消任何操作。看看docs

正如您的输出所述,object is not defined,这是因为当您在 __init__ 中引发错误时,它被视为您的类失败的初始值,并且这不会返回对象。


我想这就是你要找的东西:

class MyClass:

    def __init__(self):
        # do initialisation stuff

    def other_method(self):
        # do something
        if this_or_that:
            self.Error = specification
            raise MyCustomError(specification)  


object = MyClass()

try:
   object.other_method()
except MyCustomError as e:
    print(e)  

print(object.Error)

【讨论】:

  • 所以如果它不在__init__ 函数中,我的代码基本上可以工作吗?
  • 是的!您只需要一个初始化的类,以及对 object 的引用即可获得 error
  • @MichaelHofmann 我刚刚在我的答案中添加了一个代码 sn-p,这可能是您想要做的。
【解决方案3】:

这不是一个漂亮的解决方案,但它应该可以工作:

errorcode = None

class MyClass:
    def __init__(self):
        global errorcode
        #do something
        if this_or_that:
            errorcode = specification
            raise MyCostumError
try:
    object = MyClass()
except MyCostumError:
    print(errorcode)

【讨论】:

    【解决方案4】:

    如果您在初始化程序中引发异常,则不应依赖要创建的对象来向调用者获取一些错误信息。这是您应该使用异常来传递该信息的地方:

    class MyCustomError(Exception):
        pass
    
    class MyClass:
        def __init__(self):
            #do something
            if this_or_that:
                raise MyCustomError(specification)  # put the spec in the exception itself
    try:
        object = MyClass()
    except MyCustomError as e:
        print(e)  # the spec is in the exception object
    

    【讨论】:

      【解决方案5】:

      鉴于您的问题,我认为以下内容应该很适合您的用例。

      class MyClass:
          def __init__(self):
              # Do something
              try:
                  if this_or_that:
                          self.Error = specification
                          raise MyCostumError
              except MyCustomError as e:
                  # Handle your custom error however you like
          
      object = MyClass()
      

      在上述情况下,您应该能够通过在 MyClass.__init__ 本身内处理此行为来降低由于自定义异常/错误引发失败而导致实例化失败的风险。

      这也是一个更简洁的解决方案,它可以保持与类的 __init__ 函数中包含的 MyClass 对象的实例化相关的逻辑 - 即,您不必担心在 try 中包装此类的实例化/except 每次出现在您的代码中时都会阻塞。

      【讨论】:

        猜你喜欢
        • 2018-06-12
        • 2012-09-25
        • 1970-01-01
        • 1970-01-01
        • 2020-01-30
        • 2020-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多