【问题标题】:Named temporary file is not being deleted命名的临时文件未被删除
【发布时间】:2021-07-23 15:55:38
【问题描述】:

我正在 lambda 函数中创建一个命名的临时文件,我认为我编写的代码可能存在问题。

我创建了一个命名文件,用于创建一个 excel 文件,然后我将命名文件引用传递给另一个函数以上传到存储桶,似乎进一步调用该函数最终导致磁盘已满。

我不完全确定为什么调用 close() 不会从磁盘上的任何位置删除文件。

这是我创建 excel 文件的函数:

def get_excel_file(df_report): 
    tmp_file = tempfile.NamedTemporaryFile(suffix=".xlsx")
    

    with pd.ExcelWriter(tmp_file.name) as writer:       
        df_report.to_excel(
            writer, sheet_name="Report", index=False, startrow=4
        )
        writer.save()

    return tmp_file

然后将返回的文件tmp_file传递给以下函数进行上传,其参数名为report

def upload_renewal_report(bucket_name, report, file_name):    
    s3_client.upload_file(report.name, bucket_name, file_name)

    report.close()

代码是否有任何明显错误,这意味着文件不会被清除?

报告,我关闭的对象打印为:

WHAT IS REPORT: <tempfile._TemporaryFileWrapper object at 0x7f9aeb9d42e0>

WHAT TYPE IS REPORT: <class 'tempfile._TemporaryFileWrapper'>

有一条评论现在已被删除,这似乎暗示我没有在临时文件上调用 close。我确实打电话给close() 似乎是临时文件,但似乎在上传到 S3 后文件由于某种原因已经关闭 也许有一些东西,因为我直到现在还没有在日志中看到这个:

/opt/python/xlsxwriter/workbook.py:338: UserWarning: Calling close() on already closed file.

【问题讨论】:

  • 打印对象类型和对象后,上面发布的来自 cloudwatch 的日志,可能有助于缩小范围。
  • 最好在定义tmp_file 的同一范围内使用upload_renewel_report,或者让get_excel_file 创建一个由收件人负责删除的常规文件。
  • 或者让get_excel_file 接收一个打开的文件句柄作为参数,并让调用者担心该文件是如何创建的。
  • 您正在创建一个有点奇怪的情况,因为临时文件至少被打开了两次(因为s3_client.upload_file() 需要打开它才能进行上传)。我在想也许第二次打开可能永远不会关闭 - 软件草率地关闭它打开的所有文件是相当普遍的,尤其是在阅读它们时)。

标签: python amazon-web-services aws-lambda temporary-files


【解决方案1】:

NamedTemporaryFile 可能有些奇怪。我有一个测试可以在 linux 上运行,但不能在你描述的确切行为的 windows 上运行。我修复了它-

with NamedTemporaryFile(mode="w", delete=False) as f:
    f.write(profile)
    f.seek(0)
    yield f.name
    f.close()
    os.unlink(f.name)

您也可能实际上不需要使用磁盘(如果文件对于内存来说不是太大的话)

data = io.BinaryIO()
with pd.ExcelWriter(data) as writer:       
    df_report.to_excel(
        writer, sheet_name="Report", index=False, startrow=4
    )

s3_client.put_object(Body=data)

【讨论】:

  • 这看起来是一个非常合理的建议,所以在容器中运行了一些 ls -aldf -h 之后,我几乎看不到任何 /tmp 被占用,并且用于大型报告本地生成时大小仍然只有 60MB。最奇怪的是,我现在使用了与您的示例类似的东西,我使用 bytesIO 创建了文件,但仍然收到错误消息,告诉我设备上没有剩余空间。即使在重新部署 lambda 之后,它也将是一个新容器。它必须与 pandas excel 生成的工作方式有关,因为没有其他任何意义
  • 另外为了测试,我将函数的内存增加到 8GB,在文件系统错误发生之前它永远不会接近使用它。
  • 查看这段代码,我相信 ExcelWriter 在离开其上下文时会调用 close 。因此,您想在该块内执行 data.seek(0)s3_client.put_object(我相信)
猜你喜欢
  • 2012-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 2015-02-26
相关资源
最近更新 更多