【问题标题】:when is it necessary to add an `else` clause to a try..except in Python?什么时候需要在 Python 中的 try..except 中添加 `else` 子句?
【发布时间】:2009-08-22 13:41:42
【问题描述】:

当我用 Python 编写带有异常处理的代码时,我可以编写如下代码:

try:
    some_code_that_can_cause_an_exception()
except:
    some_code_to_handle_exceptions()
else:
    code_that_needs_to_run_when_there_are_no_exceptions()

这与以下有何不同:

try:
    some_code_that_can_cause_an_exception()
except:
    some_code_to_handle_exceptions()

code_that_needs_to_run_when_there_are_no_exceptions()

在这两种情况下,code_that_needs_to_run_when_there_are_no_exceptions() 都会在没有异常时执行。有什么区别?

【问题讨论】:

    标签: python exception


    【解决方案1】:

    在第二个示例中,code_that_needs_to_run_when_there_are_no_exceptions() 将在您确实有异常时运行,然后您处理它,在异常之后继续。

    所以...

    在这两种情况下,code_that_needs_to_run_when_there_are_no_exceptions() 将在没有异常时执行,但在后者中将在有和没有异常时执行。

    在你的 CLI 上试试这个

    #!/usr/bin/python
    
    def throws_ex( raise_it=True ):
            if raise_it:
                    raise Exception("Handle me")
    
    def do_more():
            print "doing more\n"
    
    if __name__ == "__main__":
            print "Example 1\n"
            try:
                    throws_ex()
            except Exception, e:
                    # Handle it
                    print "Handling Exception\n"
            else:
                    print "No Exceptions\n"
                    do_more()
    
            print "example 2\n"
            try:
                    throws_ex()
            except Exception, e:
                    print "Handling Exception\n"
            do_more()
    
            print "example 3\n"
            try:
                    throws_ex(False)
            except Exception, e:
                    print "Handling Exception\n"
            else:
                    do_more()
    
            print "example 4\n"
            try:
                    throws_ex(False)
            except Exception, e:
                    print "Handling Exception\n"
            do_more()
    

    会输出

    示例 1

    处理异常

    示例 2

    处理异常

    做得更多

    示例 3

    做得更多

    示例 4

    做得更多

    你明白了,玩弄例外、冒泡和其他事情!破解命令行和 VIM!

    【讨论】:

      【解决方案2】:

      其实在第二个sn-p中,最后一行总是执行。

      你可能是说

      try:
          some_code_that_can_cause_an_exception()
          code_that_needs_to_run_when_there_are_no_exceptions()
      except:
          some_code_to_handle_exceptions()
      

      我相信你可以使用else 版本,如果它使代码更具可读性。如果你不想捕获来自code_that_needs_to_run_when_there_are_no_exceptions 的异常,你可以使用else 变体。

      【讨论】:

      • 是的,第二个 sn-p 始终执行,但第一个 sn-p 和您的示例之间的可读性/风格差异不止于此。在第一个 sn-p 中,code_that_needs_to_run_where_there_are_no_exceptions() 永远不会导致 some_code_to_handle_exceptions() 运行,而在您的 sn-p 中它可以。
      • 大卫,你是对的。如您所见,我在您发表评论前大约 30 秒意识到了这一点 :)
      【解决方案3】:

      示例 1:

      try:
          a()
          b()
      except:
          c()
      

      这里,b() 只会在 a() 没有抛出的情况下运行,但是 except 块也会捕获任何可能由 b() 抛出的异常,您可能不会想。一般规则是:只捕获您知道可能发生的异常(并且有一种处理方式)。因此,如果您不知道b() 是否会抛出,或者如果您无法通过捕获b() 抛出的异常来做任何有用的事情,那么不要将b() 放入try:阻止

      示例 2:

      try:
          a()
      except:
          c()
      else:
          b()
      

      这里,b() 只会在a() 没有抛出的情况下运行,但b() 抛出的任何异常都不会在此处捕获,并将继续向上传播到堆栈。这通常是您想要的。

      示例 3:

      try:
          a()
      except:
          c()
      
      b()
      

      在这里,b() 始终运行,即使 a() 没有抛出任何东西。当然,这也很有用。

      【讨论】:

        【解决方案4】:

        您的原始代码几乎是正确的。这是完整的治疗方法:

        try:
            some_code_that_can_cause_an_exception()
        except:
            some_code_to_handle_exceptions()
        else:
            code_that_needs_to_run_when_there_are_no_exceptions()
        
        code_that_runs_whether_there_was_an_exception_or_not()
        

        【讨论】:

        • code_that_runs_whether_there_was_an_exception_or_not() 不应该在 finally 块中吗?
        【解决方案5】:

        虽然 Ned Batchelder 的回应适合 OP,但我想稍微加强一下。另外,我不能作为评论回复 Mk12 的评论(因为我“只有”有 49 个代表,而不是 50 个,请看图)。所以我的贡献:

        try:
            code_that_can_cause_an_exception()
        except ParticularException:
            code_to_handle_the_particular_exception()
        except:
            code_to_handle_all_other_exceptions()
        else:
            code_to_run_when_there_are_no_exceptions_and_which_should_not_be_run_after_except_clauses()
        finally:
            code_to_run_whether_there_was_an_exception_or_not_even_if_the_program_will_exit_from_the_try_block()
        
        code_to_run_whether_there_was_an_exception_or_not_if_execution_reaches_here()
        

        【讨论】:

          【解决方案6】:

          根据docs...

          “如果和当控制从 try 子句的末尾流出时执行可选的 else 子句。7.2 else 子句中的异常不被前面的 except 子句处理。”

          所以看看这个基本示例作为你的答案

          try:
            print("Try with Exception")
            print(sys.path)
          except NameError:
            print "Exception"
          else:
            print "Else"
          
          print("Out of try/except block")
          
          try:
            print("Try without Exception")
          except NameError:
            print "Exception"
          else:
            print "Else is now executed"
          
          print("Out of try/except finally")
          

          查看未发生异常时 else 是如何执行的。

          【讨论】:

            【解决方案7】:

            我经常使用 try:..except:..else: !

            这就是模式:try..except 应该只跨越我预期异常的一行代码。然后除了后备/默认处理,否则:做我真正想做的事情(没有例外=>继续做我想要的)。

            一个简单的例子:

               # Exhibit 1
               data_paths = []
               try:
                   from . import version_subst
               except ImportError:
                   first_datadir = "./data"
               else:
                   first_datadir = os.path.join(version_subst.DATADIR, PACKAGE_NAME)
            
            
            # Exhibit 2
            for attr in attrs:
                try:
                    obj = getattr(plugin, attr)
                except AttributeError, e:
                    if warn:
                        pretty.print_info(__name__, "Plugin %s: %s" % (plugin_name, e))
                    yield None
                else:
                    yield obj
            

            【讨论】:

              【解决方案8】:

              我已经很久没有使用 Python,但我尝试在 try 块中处理特定异常,并使用 else 来处理我可能没有预料到的“其他”异常,类似于default C/C++ 中的块 switch 块。 else 也适合这样使用吗?

              【讨论】:

              • 忽略我上面的帖子根本不起作用。为我回到书本!
              猜你喜欢
              • 1970-01-01
              • 2011-06-17
              • 1970-01-01
              • 2013-01-13
              • 2021-07-14
              • 2018-08-30
              • 2011-09-20
              • 2018-06-20
              • 2013-08-25
              相关资源
              最近更新 更多