最初,我一直在打开并同时阅读两个文件,如下所示:
with open(file1, 'r') as R1:
with open(file2, 'r') as R2:
### my code
Run Code Online (Sandbox Code Playgroud)
但现在输入文件名有时可能被gzip压缩.所以,我想拆分with语句并使用if语句来处理这两个场景,如下所示:
if zipped:
R1 = gzip.open(file1, 'r')
R2 = gzip.open(file2, 'r')
else:
R1 = open(file1, 'r')
R2 = open(file2, 'r')
with R1:
with R2:
### my code
Run Code Online (Sandbox Code Playgroud)
第二个代码的功能是否与第一个类似?或者甚至有更好的方法来做到这一点?
你正在做的事情大多有意义,但它有一个问题.
文件对象是close自己开启的上下文管理器__exit__.正如gzip文档所阐明的那样,包括GzipFile返回的对象gzip.open:
GzipFile支持io.BufferedIOBase接口,包括迭代和with语句.
所以,如果你with f:在一个打开的常规文件上写,或者GzipFile保证close在with语句之后调用它.
在Python 2.7中,细节略有不同,但它的工作方式相同.在Python 2.6,一个GzipFile是没有上下文管理.但是,有一个非常简单的解决方案(这是值得了解的其他类型的,即使你不关心的Python 2.6):你可以用任何包装close方法closing来获取调用上下文管理器close上__exit__.所以,你可以写:
with contextlib.closing(R1):
Run Code Online (Sandbox Code Playgroud)
...它会影响R1它是一个文件对象,还是其他一些GzipFile不知道如何成为上下文管理器的东西(如2.6 ).
但是,如果R1成功打开会发生什么,但会R2失败?然后你甚至没有进入with R1:异常提升的时间,所以你永远不会关闭R1.
你可以通过执行修复此with R1开幕前R2:
if zipped:
R1 = gzip.open(file1, 'r')
else:
R1 = open(file1, 'r')
with R1:
if zipped:
R2 = gzip.open(file2, 'r')
else:
R2 = open(file2, 'r')
with R2:
Run Code Online (Sandbox Code Playgroud)
或者你可以使用ExitStack.
但这里有一个更简单的解决方案:无论gzip.open和open是可调用的对象,所以你可以将它们存储在一个变量,以后调用它.由于它们具有相同的签名,并且您希望使用完全相同的参数调用它们,因此使用该变量是微不足道的:
if zipped:
zopen = gzip.open
else:
zopen = open
with zopen(file1, 'r') as R1:
with zopen(file2, 'r') as R2:
Run Code Online (Sandbox Code Playgroud)
请注意,您可以使其更简洁,而不会降低其可读性:
zopen = gzip.open if zipped else open
with zopen(file1, 'r') as R1, zopen(file2, 'r') as R2:
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
76 次 |
| 最近记录: |