避免删除 SpooledTemporaryFile
Avoiding deletion of SpooledTemporaryFile
Python 中临时文件模块的 SpooledTemporaryFile 是在系统内存中创建的临时文件,而不是在光盘上。但是,可以随时通过调用适当命名的 rollover
方法将其滚动到光盘。一旦文件关闭,它就会被删除,而这正是我要防止的。
NamedTemporaryFile 在其构造函数中有一个 delete
关键字参数来完成这项工作,但它不适用于 SpooledTemporaryFile。解决此问题的一种方法是在关闭此文件之前复制该文件。这需要额外的 copy
操作,并且必须采取预防措施以避免竞争条件。它还需要更多资源。有什么解决方法吗?
尽管io.StringIO is available at my disposal, I decided to take a look at the source code - tempfile.py。这是该模块中事件链的进展方式:
- A
SpooledTemporaryFile
作为 io.StringIO
或 io.BytesIO
对象启动。
- 回滚到光盘时,创建一个
TemporaryFile
文件对象,IO流对象被丢弃进行垃圾回收。
- 这个新文件对于几个平台是不同的。在 Windows 或 CygWin 系统上,这个新文件是
NamedTemporaryFile
,它的关闭方法通过名为 _TemporaryFileCloser
的包装器 class 访问。我们可以覆盖一些方法并跳过一些箍 * 最终设置 delete=False
以实现我们的目标。
- 在 posix 系统上,新文件只是另一个易失性 IO 流 (叹息...)
* 解决方法是将其子class 并覆盖rollover
方法。下面的代码适用于 posix 和 Windows 系统。在 Windows 上,您可以跳过 rollover
部分 - 只需要 __init__
。
from tempfile import SpooledTemporaryFile
class CustomSpooled(SpooledTemporaryFile):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# This dict will be passed on to the NamedTempFile constructor one we
# roll over our file. We are adding the delete=False argument.
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
'suffix': suffix, 'prefix': prefix,
'encoding': encoding, 'newline': newline,
'dir': dir, 'delete': False}
def rollover(self):
# This is overidden to get that NamedTemperoraryFile
# Everythng else is just the same
if self._rolled: return
file = self._file
newfile = self._file = NamedTemporaryFile(**self._TemporaryFileArgs)
del self._TemporaryFileArgs
newfile.write(file.getvalue())
newfile.seek(file.tell(), 0)
self._rolled = True
CAUTION! This is evidently a dirty hack, therefore I do not recommend this for production code or anything of the sort.
Python 中临时文件模块的 SpooledTemporaryFile 是在系统内存中创建的临时文件,而不是在光盘上。但是,可以随时通过调用适当命名的 rollover
方法将其滚动到光盘。一旦文件关闭,它就会被删除,而这正是我要防止的。
NamedTemporaryFile 在其构造函数中有一个 delete
关键字参数来完成这项工作,但它不适用于 SpooledTemporaryFile。解决此问题的一种方法是在关闭此文件之前复制该文件。这需要额外的 copy
操作,并且必须采取预防措施以避免竞争条件。它还需要更多资源。有什么解决方法吗?
尽管io.StringIO is available at my disposal, I decided to take a look at the source code - tempfile.py。这是该模块中事件链的进展方式:
- A
SpooledTemporaryFile
作为io.StringIO
或io.BytesIO
对象启动。 - 回滚到光盘时,创建一个
TemporaryFile
文件对象,IO流对象被丢弃进行垃圾回收。 - 这个新文件对于几个平台是不同的。在 Windows 或 CygWin 系统上,这个新文件是
NamedTemporaryFile
,它的关闭方法通过名为_TemporaryFileCloser
的包装器 class 访问。我们可以覆盖一些方法并跳过一些箍 * 最终设置delete=False
以实现我们的目标。 - 在 posix 系统上,新文件只是另一个易失性 IO 流 (叹息...)
* 解决方法是将其子class 并覆盖rollover
方法。下面的代码适用于 posix 和 Windows 系统。在 Windows 上,您可以跳过 rollover
部分 - 只需要 __init__
。
from tempfile import SpooledTemporaryFile
class CustomSpooled(SpooledTemporaryFile):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# This dict will be passed on to the NamedTempFile constructor one we
# roll over our file. We are adding the delete=False argument.
self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering,
'suffix': suffix, 'prefix': prefix,
'encoding': encoding, 'newline': newline,
'dir': dir, 'delete': False}
def rollover(self):
# This is overidden to get that NamedTemperoraryFile
# Everythng else is just the same
if self._rolled: return
file = self._file
newfile = self._file = NamedTemporaryFile(**self._TemporaryFileArgs)
del self._TemporaryFileArgs
newfile.write(file.getvalue())
newfile.seek(file.tell(), 0)
self._rolled = True
CAUTION! This is evidently a dirty hack, therefore I do not recommend this for production code or anything of the sort.