Shutil 复制命令写入 0 字节文件复制临时文件

And*_*ill 3 python shutil temp

我有另一种方法调用该函数 3 次来写入 3 个不同的文件。前 2 个文件按预期复制到目标文件夹,第三个文件始终为零字节。如果我关闭删除功能,我可以看到所有 3 个临时文件均已成功写入。该代码没有报告错误,但在该过程结束时,第三个文件始终为空。

有谁知道为什么这会失败三分之一次?

def write_file(file_destination: str, content: bytes):
    with tempfile.NamedTemporaryFile() as fp:
        fp.write(content)
        shutil.copy(fp.name, file_destination)
Run Code Online (Sandbox Code Playgroud)

以下变体有效,但是,我想了解为什么上面的代码中前两个文件有效而第三个文件无效。

def write_file(file_destination: str, content: bytes):
    with tempfile.NamedTemporaryFile(delete=False) as fp:
        fp.write(content)
    shutil.copy(fp.name, file_destination)
    os.remove(fp.name)
Run Code Online (Sandbox Code Playgroud)

tyr*_*ion 5

这是因为content当您执行复制时,尚未将其写入磁盘。发生这种情况是因为写入被缓冲,并且并不总是在您调用后立即发生file.write。要确保内容在给定点写入磁盘,您可以使用file.flush.

对于您的情况,将代码更改为:

def write_file(file_destination: str, content: bytes):
    with tempfile.NamedTemporaryFile() as fp:
        fp.write(content)
        fp.flush()
        shutil.copy(fp.name, file_destination)
Run Code Online (Sandbox Code Playgroud)

有关内容何时实际写入磁盘的更多信息,您可以参阅 的文档io.BufferedWriter。相关部分是:

缓冲区将在各种条件下写出到底层 RawIOBase 对象,包括:

  • 当缓冲区对于所有待处理数据而言太小时;
  • 当调用flush()时;
  • 当请求seek()时(对于BufferedRandom对象);
  • 当 BufferedWriter 对象关闭或销毁时。

因此,在您的第一个示例中,它可能仅有时有效,因为这些时候您正在写入的内容超出了缓冲区,因此需要立即写出。

相反,您的第二个示例有效,因为当您退出块时with,文件将关闭,因此需要刷新缓冲区并将其写入磁盘。