【问题标题】:Implement an optional context manager in Python在 Python 中实现一个可选的上下文管理器
【发布时间】:2017-12-19 19:55:36
【问题描述】:

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

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

但至关重要的是,不破坏现有用法,以便其他代码按原样工作?还是需要一个不同的方法来返回上下文管理器?

【问题讨论】:

  • 您能否举例说明创建文件的代码以及您希望自动运行并删除文件的代码?
  • @quamrana 确定,已更新。
  • 什么是BigFileClass?是你控制的班级吗?它是否有close 方法或其他一些执行清理的方法?
  • @user2357112 是的,我控制它。它是一个方便的类来表示磁盘上的大数据文件。

标签: python temporary-files with-statement contextmanager


【解决方案1】:

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

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

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

编辑:如果要将BigFileClass 用作上下文管理器,请为BigFileClass 定义__enter____exit__ 方法。在这种情况下,__enter__ 唯一要做的基本上就是return self

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


备注 w.r.t.架构。

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

【讨论】:

  • 如果我希望仅在代码用作with ... as dataset: 而不是旧样式dataset = ... 时删除文件怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 1970-01-01
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 2011-12-25
相关资源
最近更新 更多