当进程被杀死时,如何在Python中清除文件对象?

时间:2016-07-26 18:59:37

标签: python io terminate

当进程终止时,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 SIGTERM更改为SIGINTSIGHUPSIGKILL中的termtest.sh(注意:我在termtest.py中为SIGINT放置一个显式处理程序,因为Python不处理Ctrl+C以外的那个处理程序。在所有情况下,所有输出文件只有完整的行(没有部分写入)并且看起来没有损坏。我调用了flush()fsync()来尽量确保将数据写入磁盘,以便脚本最有可能在写入中间被中断。

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

1 个答案:

答案 0 :(得分:1)

文件不是如何“清理”的,而是如何写入文件。程序可能会对单个“数据块”(行或其他)执行多次写入,并且您可以在此过程的中间中断并最终写入部分记录。

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

编写器对象是一个Python对象,自定义编写器可以在其write()中做一些可能会破坏它的奇怪的东西,但假设它是一个常规文件对象,它应该没问题。