'with'语句在python中做了什么?

时间:2013-09-13 03:57:47

标签: python with-statement

我是Python新手。在一个连接到mysql和获取数据的教程中,我看到了with语句。我读到了它,它与try-finally块有关。但我找不到一个我能理解的简单解释。

3 个答案:

答案 0 :(得分:4)

with语句打开资源并保证在with块完成时关闭资源,而不管块如何完成。考虑一个文件:

with open('/etc/passwd', 'r') as f:
    print f.readlines()

print "file is now closed!"

即使你引发了例外,即使你有一个return,也可以保证文件在文件结束时关闭。

为了使with能够做出此保证,表达式(示例中的open())必须是上下文管理器。好消息是许多python表达式上下文管理器,但不是全部。

根据a tutorial I foundMySQLdb.connect()实际上是一个上下文管理器。

此代码:

conn = MySQLdb.connect(...)
with conn:
    cur = conn.cursor()
    cur.do_this()
    cur.do_that()

将提交或回滚命令序列作为单个事务。这意味着您不必担心异常或其他异常代码路径 - 无论您如何离开代码块,都将处理事务。

答案 1 :(得分:2)

从根本上说,它是一个对象,它使用在入口和出口处调用的自定义逻辑来划分代码块,并且可以在其构造中接受参数。您可以使用类定义自定义上下文管理器:

class ContextManager(object):

    def __init__(self, args):
        pass

    def __enter__(self):
        # Entrance logic here, called before entry of with block
        pass

    def __exit__(self, exception_type, exception_val, trace):
        # Exit logic here, called at exit of with block
        return True

然后,入口传递一个contextmanager类的实例,并且可以引用在__init__方法中创建的任何内容(文件,套接字等)。 exit方法还接收内部块和堆栈跟踪对象中引发的任何异常,如果逻辑完成而没有引发,则接收None

然后我们可以像这样使用它:

with ContextManager(myarg):
    # ... code here ...

这对许多事情很有用,例如管理资源生命周期,释放文件描述符,管理异常以及构建嵌入式DSL等更复杂的用途。

另一种(但等效的)构造方法是contextlib装饰器,它使用生成器来分隔入口和出口逻辑。

from contextlib import contextmanager

@contextmanager
def ContextManager(args):
    # Entrance logic here
    yield
    # Exit logic here

答案 2 :(得分:1)

with视为在代码块上创建“主管”(上下文管理器)。主管甚至可以在块中给出名称和引用。当代码块正常或通过异常结束时,主管会收到通知,并且可以根据发生的情况采取适当的措施。