【问题标题】:Is it possible to close a file directly after a function call是否可以在函数调用后直接关闭文件
【发布时间】:2020-05-09 03:49:20
【问题描述】:

我有以下行:

service = discovery.build('sheets', 'v4', credentials=pickle.load(open('google_sheets_token.pickle', 'rb')))

虽然实现这样的事情很简单:

with open('google_sheets_token.pickle', 'rb') as f:
    service = discovery.build('sheets', 'v4', credentials=pickle.load(f)) 

我想知道是否可以在传递给函数后自动关闭文件?

【问题讨论】:

  • 不,如果您不保留对它的引用,则不会。惯用的方法是使用上下文管理器,这就是它们的用途
  • 您只关心打开文件以供读取还是写入?
  • @Georgy 不是真的。这基本上只是说使用我在问题的第二部分中使用的方法:我很好奇是否有可能根本不使用它。

标签: python python-3.x contextmanager resource-management


【解决方案1】:

不。在 CPython 引用解释器中,如果没有发生引用循环(它们比您想象的更容易触发,所以不要假设任何内容),第一个示例将自动关闭文件,因为引用计数在函数执行后立即降至 0有问题的返回(假设它没有保存参考)。但这不是可以依赖的东西。如果您希望在 CPython 上得到保证,甚至希望在 PyPy、Jython、IronPython 等非引用计数替代解释器上获得正确行为,请使用 with 语句。如果没有 with 管理,该文件可能会 最终关闭,但无法保证何时会发生(或者即使;这是最大的努力,而不是铁定的保证)。

【讨论】:

  • 即使没有引用计数,垃圾收集器最终也会回收它。
  • @Barmar:循环垃圾收集器不会确定地回收它(它可能需要几毫秒或几小时,并且可以关闭循环GC关闭 ,使它永远不会发生),即使它有效,也不能 100% 保证在涉及任意对象时以正确的顺序关闭(支持 openio 模块已经解决了大部分错误,但是对于很长一段时间,文本编码 I/O 层或缓冲 I/O 可能在 原始底层文件 I/O 层关闭后关闭,将未刷新的数据丢弃在缓冲区中;循环GC 只是不知道先关闭哪个)。
  • 他没有具体说明,但问题中的示例是打开文件以供读取,因此缓冲区刷新应该不是问题。我肯定会为写入文件使用上下文管理器。
  • @ShadowRanger 谢谢这是一个非常有用的答案,比作为副本链接的那个要好得多(现在关于 SO 的每个问题都只是根据标题作为副本关闭了吗?)
  • @Barmar:即使是打开文件以供读取,我也曾在 ulimits 的打开文件句柄低得离谱的系统上运行;如果您经常打开和关闭文件,并且您不在 CPython 上,或者 CPython 上的某些代码路径将文件对象合并到引用循环中(捕获异常是常见原因,因为异常包含引用引用其框架的回溯,该框架引用异常本身),有可能在收集之前达到限制,现在您无法打开新文件,直到收集清除旧文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多