在Python中实现可选的上下文管理器

时间:2017-12-19 19:55:37

标签: python temporary-files with-statement contextmanager

我们有一个具有以下使用模式的代码库:

factory = DataFactory(args)
dataset = factory.download_and_cache_big_dataset(key)
metadata = dataset.get_some_metadata()

目前,download_and_cache_big_dataset从S3获取一个非常大的文件并将其放在某处。除其他外,它确实

filename = get_s3_key(key)
filepath = os.path.join(get_tmp_dir(), filename)
s3.download_file(key, filepath)
return BigFileClass(filepath) # gets stored in a class somewhere

但是,此文件不会被删除。当谨慎地调用此函数并依赖于文件缓存时,这很好,但是当它被重复调用并且我们不想填满磁盘时会很糟糕。有没有办法用context manager重构代码,以便我们可以将其用作

factory = DataFactory(args)
with factory.download_and_cache_big_dataset(key) as dataset:
    metadata = dataset.get_some_metadata()
    # do something with metadata

# file gets automatically deleted

但关键的是,不破坏现有用法,以便其他代码按原样运行?或者是否需要一个返回上下文管理器的不同方法?

1 个答案:

答案 0 :(得分:1)

由于您返回BigFileClass的实例来处理/表示数据,我建议如下。

我假设数据文件对每个实例都是唯一的。

  • 将实例变量添加到BigFileClass以跟踪数据文件的路径。
  • __del__方法添加到删除了数据文件的BigFileClass

修改:如果您想将BigFileClass用作上下文管理器,请为__enter__定义__exit__BigFileClass方法。 __enter__在这种情况下唯一必须做的事情基本上是return self

我会将删除文件的任务留给__del__方法(当BigFileClass的引用计数达到0时)。在删除数据文件后,让类实例仍然存在感觉不对。

备注w.r.t.架构。

使用工厂对我来说似乎是一种不必要的复杂情况。 IMO,download_and_cache_big_dataset可能只是一个返回BigFileClass实例的函数。