代码之家  ›  专栏  ›  技术社区  ›  Sam

Python初学者:如何防止“finally”执行?

  •  3
  • Sam  · 技术社区  · 17 年前

    # Connect to the DB
    try:
        dbi = MySQLdb.connect(host='localhost', \
                              user='user', \
                              passwd='pass', \
                              db='dbname', \
                              port=3309)
    
        print "Connected to DB ..."
    
    except MySQLdb.Error, e:
        apiErr = 2
        apiErrMsg = "Error %d: %s" % (e.args[0], e.args[1])
        return
    
        # To prevent try..finally bug in python2.4,
        # one has to nest the "try: except:" part. 
    try:
        try:
            sql = dbi.cursor()
            sql.execute("""
            SELECT *
            FROM table
            WHERE idClient =  %s
            """, (key, ))
    
            access = sql.fetchall()
    
            # [some more code here]           
    
        except MySQLdb.Error, e:
            apiErr = 2
            apiErrMsg = "Error %d: %s" % (e.args[0], e.args[1])
            return
    
    finally:
        sql.close()
        dbi.close()
    

    (注意:使用python 2.4)

    澄清:我不知道MySQLdb在发生错误时是否会自动关闭连接。我在上面的代码中遇到的问题是,当建立连接时出错(代码的第一个try块),在finally块中调用dbi.close()会引发“AttributeError:'NoneType'对象没有dbi的属性'close'”。..

    :

    # define at the start 
    dbi = None
    sql = None
    

    在最后一块中,

    if sql is not None:
        sql.close()
    if dbi is not None:
        dbi.close()
    

    3 回复  |  直到 17 年前
        1
  •  6
  •   dbr    17 年前

    else: 而不是 finally: Exception Handling 文档的一部分:

    try ... except 语句有一个可选的else子句,当存在时,它必须跟在所有except子句之后。如果try子句没有引发异常,那么它对于必须执行的代码非常有用。

    for arg in sys.argv[1:]:
        try:
            f = open(arg, 'r')
        except IOError:
            print 'cannot open', arg
        else:
            print arg, 'has', len(f.readlines()), 'lines'
            f.close()
    

    ..基本上:

    try:
        [code that might error]
    except IOError:
        [This code is only ran when IOError is raised]
    else:
        [This code is only ran when NO exception is raised]
    finally:
        [This code is always run, both if an exception is raised or not]
    
        2
  •  5
  •   duffymo    17 年前

    我认为在这种情况下,你确实想使用finally,因为你想关闭这些连接。

    我认为设计中的缺陷在于获取连接并以相同的方法执行查询。我建议将两者分开。服务类或方法知道工作单元。它应该获取连接,将其传递给执行查询的另一个类,并在完成时关闭连接。这样,查询方法可以抛出遇到的任何异常,并将清理工作留给负责连接的类或方法。

        3
  •  4
  •   Waylon Flinn    17 年前

    实现这种行为的一种方法是将“finally”块中的语句移动到“try”块的底部。这样,当抛出异常时,它们不会被执行,但在所有其他语句之后,否则它们会被执行。

    编辑:

    经过进一步讨论,似乎在你的情况下,你确实想使用“finally”。我建议您在尝试关闭连接之前,先检查连接是否已关闭。