python with

读写文件时使用with可以很好地避免文件读写出错或者是忘记写关闭文件的情况
例如,打开一个文件读写:

f=open('F:\python\mytest\mytest\.idea\contextlib_code.py')
f.read()
f.close()

或者是:

try:
    f=open('F:\python\mytest\mytest\.idea\contextlib_code.py')
    f.read()
finally: 
    f.close()

比较麻烦,使用with语句可以省事

语法:with open('/path/to/contextlib_code.py', 'r') as f:
with语句必跟__enter__()__exit__()

意义在于:
第一步:执行__enter__()将其返回值带给with
第二步:执行with
第三步:执行__exit__()
举例:

引用廖雪峰python 3教程:

#-*- coding: utf-8 -*-
"""
#使用with语句,看执行先后顺序
"""
class Query(object):
    def __init__(self,name):
        self.name=name
    def __enter__(self):  #第一步执行__enter__
        print('Begin')
        return self
    def __exit__(self,exc_type,exc_value,tracback):  #第三步执行:__exit__
        if exc_type:
            print('Error')
        else:
            print('End')
    def query(self):
        print('Query info about %s...' % self.name)

with Query('Bob') as q:                           #第二部执行:__with__
    q.query()

执行结果:

Begin
Query info about Bob...
End

原理是:

with context_expression [as target(s)]:
    with-body,

它的执行顺序是这样的

1.执行 context_expression,生成上下文管理器 context_manager

2.调用上下文管理器的 enter() 方法;如果使用了 as 子句,则将 enter() 方法的返回值赋值给 as 子句中的 target(s)

3.执行语句体 with-body

4.不管是否执行过程中是否发生了异常,执行上下文管理器的 exit() 方法,exit() 方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句 break/continue/return,则以 None 作为参数调用 exit(None, None, None) ;如果执行过程中出现异常,则使用 sys.exc_info 得到的异常信息为参数调用 exit(exc_type, exc_value, exc_traceback)

5.出现异常时,如果 exit(type, value, traceback) 返回 False,则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理
还有一种方法是使用contextlibcontextmanager简化使用__enter____exit__
使用方法:

1.用yield代替__enter__,首先执行yield前的语句,然后执行with后再次执行yield后的语句

例子:来源于廖雪峰 python3 教程

from  contextlib import contextmanager
class Query(object):
    def __init__(self,name):
        self.name=name
    def query(self):
        print('Query info about %s...' % self.name)

@contextmanager
def create_query(name):
    print('Begin')
    q=Query(name)
    yield q
    print('End')

with create_query('Bob') as q:
    q.query()

结果:

Begin
Query info about Bob...
End

当然这两种方法都是需要有上下文的,如果一个对象没有上下文,则没有办法使用withcontextmanage

@closing解决了没有上下文的情况

可以用closing()来把该对象变为上下文对象。例如,用with语句使用urlopen()

from contextlib import closing
from urllib.request import urlopen
with closing(urlopen('https://www.python.org'))as page:
    for line in page:
        print(line)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值