【问题标题】:How are file objects cleaned up in Python when the process is killed?当进程被杀死时,如何在 Python 中清理文件对象?
【发布时间】:2016-07-28 09:12:34
【问题描述】:

当进程终止时,Python 中的文件对象会发生什么? Python 是否以SIGTERMSIGKILLSIGHUP(等)或KeyboardInterrupt 异常终止是否重要?

我有一些日志记录脚本,它们不断获取数据并将其写入文件。我不关心做任何额外的清理工作,但我只想确保在 Python 突然终止时日志文件没有损坏(例如,我可以让它在后台运行并关闭计算机)。我制作了以下测试脚本来尝试看看会发生什么:

termtest.sh:

for i in $(seq 1 10); do
    python termtest.py $i & export pypid=$!
    sleep 0.3
    echo $pypid
    kill -SIGTERM $pypid
done

termtest.py:

import csv
import os
import signal
import sys

end_loop = False


def handle_interrupt(*args):
    global end_loop
    end_loop = True


signal.signal(signal.SIGINT, handle_interrupt)

with open('test' + str(sys.argv[-1]) + '.txt', 'w') as csvfile:
    writer = csv.writer(csvfile)
    for idx in range(int(1e7)):
        writer.writerow((idx, 'a' * 60000))
        csvfile.flush()
        os.fsync(csvfile.fileno())
        if end_loop:
            break

我使用不同的信号运行termtest.sh(在termtest.sh 中将SIGTERM 更改为SIGINTSIGHUPSIGKILL)(注意:我在termtest.py 中为SIGINT 放置了一个显式处理程序因为除了Ctrl+C 之外,Python 不处理那个。在所有情况下,所有输出文件都只有完整的行(没有部分写入)并且没有出现损坏。我调用了flush()fsync() 以确保尽可能多地将数据写入磁盘,以便脚本在写入过程中最有可能被中断。

那么我是否可以得出结论,Python 在终止时总是会完成写入并且不会使文件处于中间状态?还是这取决于操作系统和文件系统(我使用 Linux 和 ext4 分区进行测试)?

【问题讨论】:

    标签: python io terminate


    【解决方案1】:

    文件被“清理”的方式与其写入方式更重要。一个程序可能会为单个“块”数据(行或其他)执行多次写入,您可能会在此过程中间中断并最终写入部分记录。

    查看csv 模块的C source,它将每一行组装到一个字符串缓冲区,然后使用单个write() 调用将其写入。这通常应该是安全的;该行要么传递给操作系统,要么不传递,如果它到达操作系统,它就会全部被写入或不被写入(当然,除了硬件问题,其中一部分可能会进入坏扇区)。

    writer 对象是一个 Python 对象,自定义 writer 可能会在其 write() 中做一些奇怪的事情,这可能会破坏这一点,但假设它是一个常规文件对象,应该没问题。

    【讨论】:

      猜你喜欢
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-02
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      相关资源
      最近更新 更多