【问题标题】:How should I use try...except while defining a function?我应该如何在定义函数时使用 try...except ?
【发布时间】:2011-02-03 08:18:27
【问题描述】:

我发现我对不需要使用try..except的问题感到困惑。最近几天,我定义的几乎每个函数都使用了它,我认为这可能是一种不好的做法。例如:

class mongodb(object):

    def getRecords(self,tname,conditions=''):
        try:
            col = eval("self.db.%s" %tname)
            recs = col.find(condition)
            return recs
        except Exception,e:
            #here make some error log with e.message

我的想法是,可能到处都会引发异常,我必须使用try 来获取它们。 我的问题是,在定义函数时到处使用它是一个好习惯吗?如果没有,有什么原则吗?不胜感激!

问候

【问题讨论】:

  • 你应该使用eval("self.db.%s" %tname)而不是getattr(self.db, tname)
  • @Aaron Digulla 感谢您的来信。
  • 感谢您提供高质量的答案,但很难选择最好的答案~

标签: python exception function


【解决方案1】:

这可能不是最好的做法。例外的全部意义在于,您可以在与提出的非常不同的级别上捕获它们。最好在您有足够信息以使它们对它们有用的地方处理它们(这非常依赖于应用程序和上下文)。

例如下面的代码可以抛出 IOError("[Errno 2] No such file or directory"):

def read_data(filename):
    return open(filename).read()

在那个函数中你没有足够的信息来用它做某事,但是在你实际使用这个函数的地方,如果出现这种异常,你可以决定尝试不同的文件名或向用户显示错误,或者别的东西:

try:
    data = read_data('data-file.txt')
except IOError:
    data = read_data('another-data-file.txt')
    # or
    show_error_message("Data file was not found.")
    # or something else

【讨论】:

    【解决方案2】:

    这(非常广泛地捕获所有可能的异常)确实被认为是不好的做法。您将掩盖异常的真正原因。

    仅捕获“明确命名”类型的异常(您希望并且您可以/将优雅地处理)。让其余的(意料之外的)冒泡吧。

    您可以通过覆盖sys.excepthook 来记录这些(未捕获的)异常(全局):

    import sys
    import traceback
    # ...
    
    def my_uncaught_exception_hook(exc_type, exc_value, exc_traceback):
        msg_exc = "".join( \
                  traceback.format_exception(exc_type, exc_value, exc_traceback) )
        # ... log here...
    
    sys.excepthook = my_uncaught_exception_hook # our uncaught exception hook
    

    【讨论】:

      【解决方案3】:

      你必须在几个目标之间找到平衡:

      1. 应用程序应自行从尽可能多的错误中恢复。

      2. 应用程序应报告所有不可恢复的错误,并提供足够详细的信息来解决问题的原因。

      3. 错误可能随处发生,但您不想让所有错误处理代码污染您的代码。

      4. 应用程序不应崩溃

      要解决 #3,您可以使用exception hook。所有未处理的异常都会导致当前事务中止。在最高级别捕获它们,回滚事务(这样数据库不会变得不一致),然后再次抛出它们或吞下它们(这样应用程序就不会崩溃)。你应该使用decorators for this。这解决了 #4 和 #1。

      #2 的解决方案是经验。随着时间的推移,您将了解解决问题所需的信息。困难的部分是在发生错误时仍然拥有信息。一种解决方案是在低级方法中添加调试日志调用。

      另一种解决方案是每个线程都有一个字典,您可以在其中存储一些位并在发生错误时转储。

      【讨论】:

        【解决方案4】:

        另一种选择是将一大段代码包装在 try: except: 中(例如在 Web 应用程序中,一个特定的 GUI 页面),然后使用 sys.exc_info() 打印出错误以及堆栈所在的位置它发生了

        import sys
        import traceback
        try:
            #some buggy code    
            x = ??
        except:
            print sys.exc_info()[0] #prints the exception class
            print sys.exc_info()[1] #prints the error message
            print repr(traceback.format_tb(sys.exc_info()[2])) #prints the stack
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-08-11
          • 1970-01-01
          • 2020-05-07
          • 2018-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多