重新提出异常并不像预期的那样有效

时间:2018-03-20 12:15:24

标签: python

我有这个相当复杂的try except块:

try:
  self.sorting = sys.argv[1]
  try:
    test_sorting_var = int(self.sorting)
    if test_sorting_var < 1:
      print "Sorting column number not valid."
      raise ValueError
    else:
      self.sorting = test_sorting_var
  except ValueError:
    print "There's a problem with the sorting value provided"
    print "Either the column doesn't exists or the column number is invalid"
    print "Please try a different sorting value or omit it."
    sys.exit(1)
  except:
    if self.sorting not in self.output_table.column_headers:
      print "Sorting column name not valid."
      raise ValueError
except:
  pass

基本上我正在检查:

  1. 如果有sys.argv[1]
  2. 如果是,请将其设为int,然后查看是否小于1
  3. 如果int失败,请将其作为字符串
  4. 进行测试

    在2 + 3中,如果测试没有成功,我会提出一个ValueError,应该在except ValueError块中捕获它并按预期执行:

    Sorting column number not valid.
    There's a problem with the sorting value provided
    Either the column doesn't exists or the column number is invalid
    Please try a different sorting value or omit it.
    

    BUT!不调用sys.exit(1),程序就会继续。

    如何修复它甚至使其更具可读性?

4 个答案:

答案 0 :(得分:5)

在最后两行中,您会捕获任何例外:

except:
  pass

这包括由SystemExit引发的例外sys.exit

要解决此问题,请仅捕获源自Exceptionwhich SystemExit does not

的异常
except Exception:
  pass

一般情况下,(几乎)从来都不是一个好主意,除了,总是捕捉Exception,或者如果可能的话,更具体的东西。

答案 1 :(得分:3)

内置sys.exit()引发SystemExit - 异常。当您没有定义要捕获的异常(except:没有异常类型)时捕获任何类型的异常,SystemExit也会被捕获。最终,该函数将一直运行到您编写pass的最后一行。

要做的最好的事情就是始终捕获特定的异常,并且永远不会捕获except:的所有异常。

此外,您应该检查self.sorting是否在self.output_table.column_headers之外的try catch中,检查是否有有效的self.sorting。

答案 2 :(得分:1)

来自documentation for sys.exit

  

退出Python。这是通过引发SystemExit异常来实现的,因此可以接受try语句的finally子句指定的清理操作,并且可以拦截外层的退出尝试。

这意味着外部try except循环正在捕获SystemExit异常并导致它通过。您可以将此异常添加到外部块并再次调用它。

答案 3 :(得分:1)

我想我会做这样的事情:

import sys

def MyClass(object):
    def method(self, argv, ...):
        # ...
        if len(argv) < 2:
          raise RuntimeError("Usage: {} <sorting column>".format(argv[0]))
        sorting = argv[1]
        try:
            self.sorting = int(sorting)
        except ValueError:
            try:
                self.sorting = self.output_table.column_headers.index(sorting)
            except ValueError:
                raise ValueError("Invalid sorting column '{}'.".format(sorting))
        # ...

try:
    # ...
    obj.method(sys.argv, ...)
except Exception as e:
    sys.exit(e.message)
  • ask for forgiveness instead of permission可以使事情变得更容易(例如解析数字),但是如果你需要确定sys.argv是否有足够的元素只需检查它,它就会使程序生成流清楚。
  • 避免在常规代码中使用sys.exit,尝试仅在最外层使用它。在大多数情况下,通常最好让异常冒泡并在最高级别捕获它们,或者在必要时让它们崩溃。
  • 请使用异常参数来存储错误信息,您可以在以后决定是否打印错误,记录错误,在弹出窗口中显示,...
  • 您可以将其作为参数传递给方法/构造函数,而不是直接在类中使用sys.argv,它将使代码更容易测试,并且对未来更加灵活。