python with...as用法

转自: http://blog.youkuaiyun.com/elevenqiao/article/details/6796653
with从Python 2.5就有,需要from __future__ import with_statement。
python  2.6开始,成为默认关键字。
在What's new in python2.6/3.0中,明确提到:
The ‘
with
‘ statement is a control-flow structure whose basic
structure is:
with expression [as variable]:
with-block
也就是说with是一个控制流语句,跟if/for/while/try之类的是一类的,with可以用来简化try finally代码,看起来可以比try finally更清晰。
这里新引入了一个"上下文 管理 协议"context management protocol,实现方法是为一个类定义__enter__和__exit__两个函数。
with expresion as variable的执行过程是,首先执行__enter__函数,它的返回值会赋给as后面的variable,想让它返回什么就返回什么,只要你知道怎么处理就可以了,如果不写as variable,返回值会被忽略。
然后,开始执行with-block中的语句,不论成功失败(比如发生异常、错误,设置sys.exit()),在with-block执行完成后,会执行__exit__函数。
这样的过程其实等价于:
try:
执行 __enter__的内容
执行 with_block.
finally:
执行 __exit__内容

只不过,现在把一部分代码封装成了__enter__函数,清理代码封装成__exit__函数。
我们可以自己实现一个例子:
import sys
class test:
def __enter__(self):
       print("enter")
       return 1
def __exit__(self,*args):
       print("exit")
       return True
with test() as t:
print("t is not the result of test(), it is __enter__ returned")
print("t is 1, yes, it is {0}".format(t))
raise NameError("Hi there")
sys.exit()
print("Never here")
注意:
1,t不是test()的值,test()返回的是"context manager object",是给with用的。t获得的是__enter__函数的返回值,这是with拿到test()的对象执行之后的结果。t的值是1.
2,__exit__函数的返回值用来指示with-block部分发生的异常是否要re-raise,如果返回False,则会re-raise with-block的异常,如果返回True,则就像什么都没发生。
<think>嗯,用户想了解Pythonwith语句的用法,特别是多个as的情况。我之前学过一点,但得仔细想想怎么组织答案。 首先,with语句主要和上下文管理器有关。上下文管理器需要实现__enter__和__exit__方法。记得with语句能自动管理资源,比如文件操作,不用手动close了。那用户提到的多个as,可能是指同时使用多个上下文管理器的情况。 比如,同时打开两个文件的时候,可能会用with open(...) as f1, open(...) as f2。这种情况下,每个open返回的文件对象都是一个上下文管理器。需要解释这种嵌套写法,以及Python 2.7之后允许的逗号分隔写法。 还要注意执行顺序,多个上下文管理器的进入顺序是从左到右,退出顺序是相反,即后进先出。这可能会影响资源释放的顺序,比如先打开的文件后关闭? 然后,用户可能需要例子来说明多个as的使用。比如同时操作两个文件,一个读一个写。或者结合自定义的上下文管理器,比如数据库连接和锁同时管理的情况。 另外,异常处理方面,如果在with块中发生异常,各个上下文管理器的__exit__方法都会被调用,确保资源释放。需要说明多个管理器的情况下,异常是如何处理的,是否会影响其他管理器的释放。 还要提到在旧版本Python中,可能需要嵌套多个with语句,而新版本可以用逗号分隔。这可能会让代码更简洁。 有没有可能用户混淆了多个as和多个上下文管理器?比如,是否每个as对应一个上下文管理器?是的,每个as前面的表达式应该返回一个上下文管理器,然后as后面的变量是__enter__的返回值。 可能需要举一个例子,比如同时使用文件和锁,或者同时打开两个网络连接。这样用户能更直观地理解多个资源同时管理的情况。 总结一下,回答的结构应该是:基本语法,多个管理器的写法,执行顺序,异常处理,使用示例,注意事项。这样用户能一步步理解。 另外,用户提供的引用资料里提到基于类实现和生成器实现上下文管理器,可能可以提到如何自定义多个管理器的情况,但用户的问题主要集中在多个as的使用,所以可能不需要深入自定义的细节,除非例子需要。 可能还需要注意,多个上下文管理器之间如果有依赖关系,比如第二个依赖第一个的资源,这时候写法上要确保顺序正确。比如先打开数据库连接,再获取游标,但这种情况可能需要嵌套使用,或者分开with语句? 总之,要确保回答清晰,覆盖多个as的语法、执行顺序、实际例子和注意事项,帮助用户正确理解和使用。</think>### Python中`with as`语句详解(多上下文管理器) #### 一、基础语法回顾 Python的`with as`语句通过上下文管理器实现资源自动管理,要求对象必须实现`__enter__()`和`__exit__()`方法[^3]。基本语法为: ```python with ContextManager() as resource: # 使用resource的代码块 ``` #### 二、多上下文管理器的语法 当需要**同时管理多个资源**时,可通过以下两种方式实现: 1. **Python 3.10+ / 2.7+ 的逗号分隔写法** ```python with open('a.txt') as f1, open('b.txt') as f2: data = f1.read() f2.write(data) ``` 2. **旧版本嵌套写法** ```python with open('a.txt') as f1: with open('b.txt') as f2: data = f1.read() f2.write(data) ``` #### 三、执行顺序与生命周期 1. **进入顺序**:从左到右依次调用各上下文管理器的`__enter__()`方法 2. **退出顺序**:从右到左依次调用`__exit__()`方法(后进先出) 3. **异常处理**:任一阶段发生异常,仍会保证所有已打开资源的`__exit__()`被调用[^3] #### 四、典型应用场景示例 1. **文件+锁组合操作** ```python import threading lock = threading.Lock() with open('log.txt', 'a') as f, lock: f.write('线程安全写入\n') ``` 2. **数据库连接池+事务管理** ```python class DatabaseConnection: def __enter__(self): print("建立数据库连接") return self def __exit__(self, *args): print("关闭数据库连接") class Transaction: def __enter__(self): print("开始事务") def __exit__(self, exc_type, *args): if exc_type: print("回滚事务") else: print("提交事务") with DatabaseConnection() as db, Transaction(): print("执行数据库操作") ``` #### 五、注意事项 1. **变量作用域**:各`as`变量仅在`with`块内有效 2. **异常处理优先级**:首个发生的异常会被传播,后续资源仍会正常释放 3. **性能影响**:同时管理过多资源可能增加内存压力 4. **版本兼容性**:逗号分隔写法要求Python ≥2.7 #### 六、底层原理拆解 当使用多上下文管理器时,等效于: ```python mgr1 = Context1() mgr2 = Context2() res1 = mgr1.__enter__() res2 = mgr2.__enter__() try: # 执行代码块 except: mgr1.__exit__(*sys.exc_info()) mgr2.__exit__(*sys.exc_info()) raise else: mgr1.__exit__(None, None, None) mgr2.__exit__(None, None, None) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值