【问题标题】:How do I persist to disk a temporary file using Python?如何使用 Python 将临时文件持久保存到磁盘?
【发布时间】:2010-09-10 18:49:48
【问题描述】:

我正在尝试使用“tempfile”模块来操作和创建文本文件。文件准备好后,我想将其保存到磁盘。我认为这就像使用'shutil.copy'一样简单。但是,我得到一个“权限被拒绝”的 IOError:

>>> import tempfile, shutil
>>> f = tempfile.TemporaryFile(mode ='w+t')
>>> f.write('foo')
>>> shutil.copy(f.name, 'bar.txt')

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    shutil.copy(f.name, 'bar.txt')
  File "C:\Python25\lib\shutil.py", line 80, in copy
    copyfile(src, dst)
  File "C:\Python25\lib\shutil.py", line 46, in copyfile
    fsrc = open(src, 'rb')
IOError: [Errno 13] Permission denied: 'c:\\docume~1\\me\\locals~1\\temp\\tmpvqq3go'
>>> 

这不是在使用“tempfile”库时的意图吗?有一个更好的方法吗? (也许我忽略了一些非常琐碎的事情)

【问题讨论】:

    标签: python temporary-files


    【解决方案1】:

    hop 是对的,而且 dF。错误发生的原因不正确。

    由于您尚未致电f.close(),因此该文件被删除。

    docNamedTemporaryFile 表示:

    在命名的临时文件仍处于打开状态时,该名称是否可用于第二次打开文件,因平台而异(在 Unix 上可以这样使用;在 Windows NT 或更高版本上不能)。

    对于TemporaryFile

    在 Unix 下,文件的目录项在文件创建后立即被删除。其他平台不支持;您的代码不应依赖于使用此函数创建的临时文件,该文件在文件系统中具有或不具有可见名称。

    因此,要保留一个临时文件(在 Windows 上),您可以执行以下操作:

    import tempfile, shutil
    f = tempfile.NamedTemporaryFile(mode='w+t', delete=False)
    f.write('foo')
    file_name = f.name
    f.close()
    shutil.copy(file_name, 'bar.txt')
    os.remove(file_name)
    

    Hans Sjunnesson 提供的解决方案也是关闭的,因为copyfileobj 只从类文件对象复制到类文件对象,而不是文件名:

    shutil.copyfileobj(fsrc, fdst[, length])

    将类文件对象fsrc的内容复制到类文件对象fdst。整数长度(如果给定)是缓冲区大小。特别是,负长度值意味着复制数据而不以块的形式循环源数据;默认情况下,数据以块的形式读取,以避免不受控制的内存消耗。注意如果fsrc对象的当前文件位置不为0,则只会复制当前文件位置到文件末尾的内容。

    【讨论】:

    • @KayZhu 除了没有delete=Falseshutil.copy 将不起作用,导致原来的IOError 开始这个线程!所以在这种情况下我同意@jedierikb,你需要os.remove
    • 另外,从NamedTemporaryFile返回的对象是一个类文件对象,所以它可以shutil.copyfileobj一起使用。
    【解决方案2】:

    您使用TemporaryFileNamedTemporaryFile 创建的文件在关闭时会自动删除,这就是您收到错误消息的原因。如果你不想要这个,你可以改用mkstemp(参见tempfile的文档)。

    >>> import tempfile, shutil, os
    >>> fd, path = tempfile.mkstemp()
    >>> os.write(fd, 'foo')
    >>> os.close(fd)
    >>> shutil.copy(path, 'bar.txt')
    >>> os.remove(path)
    

    【讨论】:

    • 我认为错误来自这样一个事实,即您无法在文件仍处于打开状态时再次访问该文件(根据文档,这仅在 Windows 上如此)
    • Kay Z 下面有一个正确答案。另外,她/他解释得更好。
    • 谢谢。这个答案很有见地,因为它让我知道如何在 with/as 语句结束时创建一个临时目录而不被删除,因为mkdtemp 的工作原理很像mkstemp
    • TemporaryFile 打开文件句柄,shutil 尝试第二次打开文件进行写入,does not work on Windows,正如@hop 指出的那样。
    • 这不是原因,您可以编辑您的答案以使其正确吗?
    【解决方案3】:

    从 python 2.6 开始,您还可以使用 NamedTemporaryFile 并将 delete= 选项设置为 False。这样,即使您关闭临时文件,也可以访问它。

    请注意,在 Windows(NT 和更高版本)上,当文件仍处于打开状态时,您无法再次访问该文件。您必须先关闭它,然后才能复制它。在 Unix 系统上不是这样。

    【讨论】:

      【解决方案4】:

      在您的示例中,您始终可以使用 shutil.copyfileobj

      new_file = open('bar.txt', 'rw')
      shutil.copyfileobj(f, new_file)
      

      【讨论】:

      • 我认为这是正确的答案,但要注意一点:您可能必须先添加'f.seek(0)'。
      • 您能否详细说明“rw”模式与“r+”和“w+”模式有何不同?实际上我不能使用它,我收到了一个 ValueError 的消息,它是 must have exactly one of create/read/write/append mode...
      • Jyrrka:哇,这是过去的爆炸!如果您查看open() 的文档:docs.python.org/3/library/functions.html#open 然后您会看到模式在是否截断文件方面有所不同。
      • 是的,rw 在 Python 3 中似乎是一种无效模式,您对 rw 的意图是什么? (w 还不够吗?)
      • @HansSjunnesson 是的,rw 在 Python 3 中似乎是一种无效模式,你对 rw 的意图是什么?一些w版本不够吗? wb 为我工作 :)
      猜你喜欢
      • 2019-10-30
      • 2016-10-31
      • 1970-01-01
      • 2014-08-18
      • 2020-10-08
      • 1970-01-01
      • 1970-01-01
      • 2016-07-22
      • 2013-12-19
      相关资源
      最近更新 更多