我是Python新手。在一个连接到mysql和获取数据的教程中,我看到了with
语句。我读到了它,它与try-finally
块有关。但我找不到一个我能理解的简单解释。
答案 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 found,MySQLdb.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
视为在代码块上创建“主管”(上下文管理器)。主管甚至可以在块中给出名称和引用。当代码块正常或通过异常结束时,主管会收到通知,并且可以根据发生的情况采取适当的措施。