如何使用Python的关闭上下文管理器

7

标准库中的open函数既可以作为一个函数使用:

f = open('file.txt')
print(type(f))
<type 'file'>

或者作为上下文管理器:

with open('file.txt') as f:
    print(type(f))
<type 'file'>

我正在尝试使用contextlib.closing来模仿这种行为,其中File是我的自定义文件I/O类:

def my_open(filename):
    f = File(filename)
    f.open()
    return closing(f)

这作为上下文管理器按预期工作:

with my_open('file.txt') as f:
    print(type(f))
<class '__main__.File'>

但如果我直接调用,我会得到closing对象而不是我的对象:

f = my_open(filename)
print(type(f))
<class 'contextlib.closing'>

那么,我该如何实现my_open,使其既能作为上下文管理器使用,又能在直接调用时返回我的文件对象呢?

在 GitHub 上有一个完整的工作示例: https://gist.github.com/1352573


1
这不是 closing 的作用。当您编写 with 以将任何具有 close 方法的对象转换为上下文管理器时,您使用 closing。您不会提前使用它。contextlib 文档中的示例似乎非常清晰。如果您想随时将其转换为上下文管理器,则 Zach 的答案是正确的。 - agf
1个回答

13

最简单的方法可能就是自己实现__enter____exit__方法了。像这样做应该就可以了:

class File(object):
   # ... all the methods you already have ...

   # context management
   def __enter__(self):
       return self

   def __exit__(self, *exc_info):
       self.close()

顺便提一下,在你的__init__方法中完成open方法的工作会更符合惯用语。

1
还有一种可能性——在__exit__中完成close的工作,然后将close = __exit__,或者反过来。 - agf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接