013-with open() as 的用法 和 with上下文管理器(Context manager)

with open() as 的用法 和 with上下文管理器(Context manager)


一、基础读写:

读⽂件:

1、以读的⽅式打开⽂件

f = open(“1.txt”, “r”)

2、读取⽂件内容

str = f.read()

print(str)

3、关闭⽂件

f.close()

写⽂件:

1、以写的⽅式打开⽂件

f = open(“2.txt”, “w”)

2、写⼊⽂件内容

str = f.write(“Welcome to 北京!”)

3、关闭⽂件

f.close()


二、 错误代码示范:

这种⽅式存在的问题是什么?

1、以读的⽅式打开⽂件

f = open(“1.txt”, “r”)

2、读取⽂件内容

f.write(“xxxxx”)

f.close()

由于⽂件读写时都有可能产⽣ IOError ,⼀旦出错,后⾯的 f.close() 就不会调⽤。

三、优化代码:

1)为了保 证⽆论是否出错都能正确地关闭⽂件,我们可以使⽤ try … finally 来实现:

try:

1、以读的⽅式打开⽂件

f = open(“1.txt”, “r”)

2、读取⽂件内容

f.write(“xxxxx”)

except IOError as e:

print(“⽂件操作出错”, e)

finally:

f.close()

2)Python引⼊了 with 语句来⾃动帮我们调⽤ close() ⽅法:

try:

1、以读的⽅式打开⽂件

with open(“1.txt”, “r”) as f:

2、读取⽂件内容

f.write(“xxxxx”)

except IOError as e:

print(“⽂件操作出错”, e)

》这和前⾯的 try … finally 是⼀样的,但是代码更佳简洁,并且不必调⽤ f.close() ⽅法。

》使⽤ with 关键字。open ⽅法的返回值赋值给变量 f,当离开 with 代码块 的时候,系统能够⾃动调⽤ f.close() ⽅法


四、 with 的原理之上下文管理器

with 的原理前要涉及到另 外⼀个概念,就是上下⽂管理器(Context Manager)。

1)上下文理解成(语言)环境就可以,(⽽且上下⽂虽然叫上下⽂,但是程序⾥⾯⼀ 般都只有上⽂⽽已,只是叫的好听叫上下⽂。。

2)上下⽂管理器本质就是能够⽀持with操作。 任何实现了__enter__() 和 __exit__()⽅法的对象都可称之为上下⽂管理器,上下⽂管理器对象可以使 ⽤ with 关键字。显然,⽂件(file)对象也实现了上下⽂管理器协议。

一、代码演示:
"""
类:  MyFile()
类方法:
   1. __enter__()  上文方法
   2. __exit__()   下文方法
   3. __init__()   方法,接收参数并且初始化

目的:验证上下⽂管理器(Context Manager)
   with MyFile('hello.txt', 'r') as file:
       file.read()
   
"""

class MyFile(object):

   # 1. __enter__()  上文方法
   def __enter__(self):
       print("进入上文....")
       # 1,打开文件 
       self.file = open(self.file_name, self.file_model)
       # 2,返回打开的文件资源
       return self.file

   # 2. __exit__()   下文方法
   def __exit__(self, exc_type, exc_val, exc_tb):
       print("进入下文....")
       # 关闭文件资源
       self.file.close()

   # 3. __init__()   方法,接收参数并且初始化
   def __init__(self, file_name, file_model):
       # 局部变量定义成实例属性 -> 在类里面调用
       # 保存文件名和文件打开模式 -> 到实例属性中
       self.file_name = file_name
       self.file_model = file_model


if __name__ == '__main__':

   with MyFile("hello.txt", "r") as file:
       # 开始读取文件
       file_data = file.read()
       print(file_data)
       

执行结果:

进入上文....
hello,python!
进入下文.... 

__enter__()⽅法返回资源对象,这⾥就是你将要打开的那个⽂件对象,__exit__()⽅法做⼀些清除⼯作。

因为 File 类实现了上下⽂管理器,所以就可以使⽤ with 语句了。

二、实现上下⽂管理器的另外⽅式

Python 提供了⼀个 contextmanager 模块的装饰器@contextmanager,更进⼀步简化了上下⽂管理器的实现⽅式。通过 yield 将函数分割成两部分,yield 之前的语句在__enter__ ()⽅法中执⾏,yield 之后的语句在__exit__()⽅法中执⾏。紧跟在 yield 后⾯的值是 函数的返回值。

装饰器:不修改(待修饰函数)原函数的代码,增加新的功能(方法)

"""
思路:
    def myopen(file_name,file_model)

            上文(打开资源)
            yield
            下文(关闭资源)

装饰器装饰函数的步骤:
1. 导入模块 from contextlib import contextmanager
2. 开始装饰 @contextmanager


"""
from contextlib import contextmanager


@contextmanager
def myopen(file_name,file_model):

    print("进入上文")
    # 1.打开文件
    file = open(file_name,file_model)
    # 2.返回资源
    yield file
    print("进入下文")
    # 下文
    # 3. 关闭资源
    file.close()


with myopen("hello.txt", "r") as file:
    file_data = file.read()
    print(file_data)
     

执行结果:

进入上文....
hello,python!
进入下文.... 

五、 总结

1)Python 提供了 with 语法⽤于简化资源操作的后续清除操作,实现原理建⽴在上下⽂管理器协议 (__enter____exit__)之上

2)with使⽤代码中如果在打开过程中发⽣异常,需要使⽤try-except进⾏捕获

3)Python 还提供了⼀个 contextmanager 装饰器,更进⼀步简化上下管理器的实现⽅式。


六、应用with open() as

1.创建 写文件
request_data = urllib.request.urlopen(img_url)

#在(指定路径下 )--> 创建文件 --> 准备保存
 
with open('/home/cfl/Desktop/+ file_name, "wb") as file:

#在(当前目录) --> 创建文件 --> 准备保存

with open(file_name, "wb") as file:
          while True:
                file_data = request_data.read(1024)
                if file_data:
                    file.write(file_data)
                else:
                    break
2.打开 读文件

recv_data = new_client_socket.recv(1024)
file_name = recv_data.decode()
#根据文件名读取文件内容
try:
with open(file_name, “rb”) as file:
把读取的文件内容发送给客户端(循环)
while True:
file_data = file.read(1024)
判断是否读取到了文件的末尾
if file_data:
发送文件
new_client_socket.send(file_data)
else:
break
except Exception as e:
print(“文件%s下载失败” % file_name)
else:
print(“文件%s下载成功” % file_name

猜你喜欢

转载自blog.csdn.net/mmmmmCJP/article/details/109596451