【问题标题】:Why doesn't Python `NamedTemporaryFile` default `delete` to `False`?为什么 Python `NamedTemporaryFile` 不默认 `delete` 为 `False`?
【发布时间】:2015-10-30 07:17:53
【问题描述】:

我试图在 Python 3 中使用tempfile.NamedTemporaryFile。我发现如果我想通过传递新文件名来调用使用subprocess.call 或类似的任何其他进程,我必须使用delete = false,然后再使用使用os.unlink 自己手动删除文件。我认为在允许另一个进程打开它之前我必须close() 文件(在我的情况下,调用编译器来编译从 Python 创建的源文件),显然该文件在关闭时被删除。

我想知道,当 Python 已经提供了tempfile.TemporaryFile 来生成没有名称的临时文件时,如果不是为了让其他进程能够访问它们,那么 named 临时文件有什么用?

在我看来,默认应该是在文件关闭时删除创建的文件,并将删除临时文件的责任推给用户,不是吗?事实上,delete 参数本身似乎没有意义,因为如果文件无论如何都会被删除,那我们为什么需要它的名字,所以NamedTemporaryFile 永远不应该删除......

【问题讨论】:

    标签: python temporary-files


    【解决方案1】:

    认为您必须先关闭文件才能让其他进程访问它是错误的假设。事实上,正如您所观察到的,当您在 NamedTemporaryFile 上调用 close 时,它​​会默认删除磁盘上的文件。

    tempfiles 与所有 Python 一样,范围和生命周期都很重要。这是面向对象语言的一大优点,对象在不再需要时会自行清理(删除或超出范围)。在销毁时,tempfile 对象释放内存中的所有资源和磁盘上的命名文件。

    因此,如果您想通过使用文件系统名称来使用磁盘上的临时文件,NamedTemporaryFile 应该在范围内并且未关闭。不能保证在所有平台上都可以,但在 Unix/Linux 上,其他进程应该可以在文件系统中访问该文件。但是,NamedTemporaryFile 创建的文件只能由所有者读写(unix 权限 0600:-rw-------)。

    如果你想/需要自己做更多的管理和清理工作,你可以考虑使用较低级别的函数tempfile.mkstemp()。例如,

    fd, tempfilename = tempfile.mkstemp()
    f = os.fdopen(fd)
    

    在任何一种情况下,请确保在将文件名提供给另一个进程 file.flush() 之前刷新缓冲区。

    【讨论】:

    • 所以在回答我的原始查询时,您是说默认删除的原因是因为这是 Python 对象的预期行为,任何想要否则的人都应该特别询问?
    • 部分原因是我在说他们为什么会这样。
    • QTTemporaryFile 不是用 Python 编写的,其行为方式基本相同。这就是大多数人期望在面向对象语言中管理临时文件的方式。临时文件的全部意义在于它们是临时的——它们应该在不再需要时消失。如果您的需求或想要不同,是的,您可以“明确要求”该对象执行您想要的操作,或者您可以使用该语言的任何其他功能以不同的方式专门执行您想要或需要的 .
    • 并且还说,至少在 unix/linux 上,其他进程可以通过名称访问磁盘上的NamedTemporaryFile:1)只要NamedTemporaryFile object 继续存在 2) 当delete 设置为false 时无限期地存在。
    • 我错过了 .flush() :/
    【解决方案2】:

    这样您就可以在with 语句中将其用作上下文管理器,并且您可以通过name 属性获取文件名。考虑:

    with tempfile.NamedTemporaryFile() as tmp_file:
        subprocess.call(['foo', tmp_file.name])
        do_something_with(tmp_file)
    

    这将在with 语句的主体正常或异常退出时自动删除文件。

    【讨论】:

    • ... 嗯,我希望我不是很密​​集,但我不明白你的意思,因为我可以用TemporaryFile 做同样的事情...
    • 谢谢,但这很明显,它没有回答为什么delete 不默认为False...
    【解决方案3】:

    1 是什么让您说您无法访问临时文件。如果您编写 fork 代码并且文件未关闭,您仍然可以访问它。FH "are" 在 fork 进程中也是如此

    2 如果删除文件的责任在用户身上,那么我认为不需要这样的模块。如果我想保留文件,那么我会自己处理它,但如果我只需要写入文件而不用担心它,那么我会使用 temofile 模块,该模块非常好,可以让我保留文件如果我真的需要

    【讨论】:

    • subprocess.call() 创建一个新进程,而不是一个分叉。
    • 很抱歉,但这些答案似乎都没有解决问题的重点,这就是为什么 delete 默认为 false...
    • tempfile.NamedTemporaryFile 的默认值为 False 吗? 3.5:tempfile.NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None, delete=True) 3.4: tempfile.NamedTemporaryFile (mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None, delete=True) 2.7.10:tempfile.NamedTemporaryFile([mode ='w+b'[, bufsize=-1[, suffix=''[, prefix='tmp'[, dir=None[, delete=True]]]]]])
    • 对不起,我的意思是为什么它默认为false,如原始问题中所问...
    • 我相信已经回答了。因为如果你想要一个临时文件,你不想担心清理。如果要持久化数据,则不要将其保存到临时文件中。但是 tempfile 模块仍然允许您将文件保留为 namedtempfile
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2010-11-04
    • 1970-01-01
    • 2014-08-01
    • 2023-03-08
    • 2018-06-14
    相关资源
    最近更新 更多