下午小伙伴问了一个有趣的问题, 怎么用 Python 的 with 语句同时打开多个文件?

首先, Python 本身是支持同时在 with 中打开多个文件的

with open('a.txt', 'r') as a, open('b.txt', 'r') as b:
print(a.read())
print(b.read())

当然, 小伙伴的问题不可能这么简单, 他需要从打开一个列表中的所有文件, 而不是打开固定的一个文件, 这时候上面的语法显然就没法满足要求了. 幸运的是 with 语句是遵循协议的, 我们只要自定义出__enter__方法和__exit__方法就可以使用 with 语句打开自定义的类.比如我们定义以下类, 用于同时打开多个文件:

#!/usr/bin/env python
# coding: utf-8 class open_many: def __init__(self, files=None, mode='r'):
if files is None:
self._files = []
else:
self._files = files
self.mode = mode
self.fds = [] # fd is short for file descriptor def __enter__(self):
print('-->enter')
for f in self._files:
print('-->opening file')
self.fds.append(open(f, self.mode))
return self.fds def __exit__(self, exc_type, exc_val, traceback):
print('-->exit')
for fd in self.fds:
print('-->closing file')
fd.close()
if exc_type == ValueError:
print('-->exception: ' + str(exc_val))
return True if __name__ == '__main__':
print('')
with open_many(['a.txt', 'b.txt'], 'r') as files:
for f in files:
print f.read()
print('')
with open_many() as files:
raise ValueError('captured')
print('')
with open_many() as files:
raise Exception('uncaptureable')

运行结果如下:

其中__enter__方法会被进入 with 语句时调用, 返回值会作为 as 后面变量的值. __exit__方法的三个参数分别是发生的异常的类型, 异常变量, 和发生异常时的 traceback. 如果在__exit__中能够处理异常, 那么应该返回True, 否则应该返回 False. 需要注意的是, 并不需要再次把异常抛出. 这里处理的异常实在 with 语句块中发生的异常

显然为了使用 with 还需要定义一个类有点过于复杂了, Python 还提供了另一种方法, 使用 contextlib.contextmanager 装饰器和生成器来实现

#!/usr/bin/env python
# coding: utf-8 from contextlib import contextmanager @contextmanager
def open_many(files=None, mode='r'):
if files is None:
files = []
try: #相当于__enter__
fds = []
for f in files:
fds.append(open(f, mode))
yield fds
except ValueError as e:
print(e)
finally: #相当于__exit__
for fd in fds:
fd.close() if __name__ == '__main__':
with open_many(['a.txt', 'b.txt'], 'r') as files:
for f in files:
print(f.read())

此外, contextlib 中还提供了 closing 语句, 使用这个语句可以自动调用类的 close 方法.

#!/usr/bin/env python
# coding: utf-8 from contextlib import closing class Connection: def open(self):
print('opened') def close(self):
print('closed') if __name__ == '__main__':
with closing(Connection()) as con:
con.open()
# do stuff with con

Python中使用with语句同时打开多个文件的更多相关文章

  1. 详解Python中的循环语句的用法

    一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...

  2. 归纳整理Python中的控制流语句的知识点

    归纳整理Python中的控制流语句的知识点 Python 解释器在其最简单的级别,以类似的方式操作,即从程序的顶端开始,然后一行一行地顺序执行程序语句.例如,清单 1 展示了几个简单的语句.当把它们键 ...

  3. 一文了解Python中的判断语句

    判断(if)语句 目标 开发中的应用场景 if 语句体验 if 语句进阶 综合应用 01. 开发中的应用场景 生活中的判断几乎是无所不在的,我们每天都在做各种各样的选择,如果这样?如果那样?…… 程序 ...

  4. Python中表达式和语句及for、while循环练习

    Python中表达式和语句及for.while循环练习 1)表达式 常用的表达式操作符: x + y, x - y x * y, x / y, x // y, x % y 逻辑运算: x or y, ...

  5. Python教程:Python中的for 语句

    Python 中的 for 语句与你在 C 或 Pascal 中可能用到的有所不同. Python教程 中的 for 语句并不总是对算术递增的数值进行迭代(如同 Pascal),或是给予用户定义迭代步 ...

  6. Python中的import语句

    Python中的import语句是导入一个文件,这条语句主要做三件事: 1 通过一定的方式,搜寻要导入的文件: 2 如果需要,就编译这个文件: 3 运行这个文件 但是,需要注意的是,所有这三个步骤,都 ...

  7. Python中使用第三方库xlrd来写入Excel文件示例

    Python中使用第三方库xlrd来写入Excel文件示例 这一篇文章就来介绍下,如何来写Excel,写Excel我们需要使用第三方库xlwt,和xlrd一样,xlrd表示read xls,xlwt表 ...

  8. Python中的基本语句

    本文简单的介绍下Python的几个基本语句. print语句 print可同时打印多个表达式,只要将他们用逗号隔开. >>> name='Gumy' >>> gre ...

  9. python中的判断语句与循环语句

    if语句 每条if语句的核心都是一个值为Ture或False的表达式,这种表达式被称为为条件测试.if语句检查程序当前状态,并据此采取相应的措施.如果条件测试的值为Ture,Python就执行紧跟在i ...

随机推荐

  1. PTVS在Visual Studio中的安装

    下载链接,点这里 PTVS是VS下的python开发插件 1.下载完成后,双击运行,安装完毕 2.解释脚本:打开VS,找到文件-新建-项目,在新建项目页面的左侧树形菜单的已安装->模板-> ...

  2. 10分钟精通SharePoint - SharePoint定位

    平台 – "一栋楼房的框架结构" 扩展 – "用户可以根据自己需要随意装修房间"集成 – "插拔式的系统集成能力"业务– "既是全 ...

  3. php+apache+mysql的安装

    1.LAMP的安装顺序问题,现在是默认安装好了Linux系统,我的版本是Ubuntu 12.04.一般来说比较建议的顺序是Mysql Apache 最后安装PHP,在我实践下来 Apache和Mysq ...

  4. XShell连接本地Ubuntu虚拟机

    VMware Workstation 安装好本地虚拟机之后,直接在虚拟机上敲命令着实不方便. 这个时候我们就需要一个远程命令工具来管理虚拟机,这里推荐使用XShell远程命令行工具 1.下载工具 直接 ...

  5. 使用 POJO 对象绑定请求参数

    概述 Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值并且支持级联属性.这一特性在日常开发过程中使用频率比较高,开发效率也高,本文主要对 POJO 对象绑定 ...

  6. 零件库管理信息系统设计--part03:管理员登录部分设计

    兄弟们,我又回来啦! 上次我把表建完了.今天来点干货,我们用ssm框架来先简单实现一下管理员的登录功能. 在实现之前,我对user表(管理员表)做了些简单的修改,先来看看: 忽略哪些蓝色的马赛克和乱输 ...

  7. R语言基因组数据分析可能会用到的data.table函数整理

    R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理快,内部 ...

  8. 免安装版Tomcat配置内存

    去安装目录下 找 bin 目录找到这个文件 catalina.bat在文件的头部加上 set JAVA_OPTS=-Xms512m -Xmx512m -Xss1024k具体大小自己调整

  9. ie旋转滤镜Matrix

    旋转一个元素算是一个比较常见的需求了吧,在支持CSS3的浏览器中可以使用transform很容易地实现,这里有介绍:http://www.css88.com/archives/2168,这里有演示ht ...

  10. 性能测试分享:Jmeter的api监控工具解决方案

    性能测试分享:Jmeter的api监控工具解决方案 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询q ...