python - 当进程被终止时,如何在 Python 中清理文件对象?

标签 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 in termtest.sh)处理那个而不是 Ctrl+C)。在所有情况下,所有输出文件都只有完整的行(没有部分写入)并且没有出现损坏。我调用了 flush()fsync() 来尝试确保数据被尽可能多地写入磁盘,以便脚本有最大的机会在写入过程中被打断。

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

最佳答案

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

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

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

关于python - 当进程被终止时,如何在 Python 中清理文件对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38597876/

相关文章:

python - pyodbc 在 sp_prepexec 之后调用 sp_unprepare。这会影响参数化查询的性能吗?

python - 如何导入文本文件以适合此聚类算法?

python - 在python中查找重叠的时间段

Haskell sequencelistIO [a -> IO a] -> a -> IO a

python - 从字符串创建二维字典

ios - 由于未捕获的异常而终止应用程序 'NSUnknownKeyException' - IOS

c - 如何在 C 中完成这项任务?第2部分

python - python 单元测试的基本测试用例类

multithreading - Haskell forkIO 线程使用 putStrLn 在彼此之上写入

c# - 代码运行时退出 Interop 控制的 Excel