2016-07-26 24 views
1

當進程終止時,Python中的文件對象會發生什麼? Python是否以SIGTERMSIGKILLSIGHUP(等)或KeyboardInterrupt異常終止有關係嗎?當進程被終止時,如何在Python中清理文件對象?

我有一些日誌腳本不斷獲取數據並將其寫入文件。我不在乎做任何額外的清理,但我只是想確保當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不同的信號(改變SIGTERMSIGINTSIGHUPSIGKILL in termtest.sh)(注意:我在termtest.py中放置了一個明確的處理程序SIGINT,因爲Python不能處理Ctrl+C以外的那個)。在所有情況下,所有輸出文件都只有完整的行(沒有部分寫入),並且沒有出現損壞。我把flush()fsync()調用試圖確保數據儘可能寫入磁盤,以便腳本在寫入過程中被中斷的可能性最大。

因此,我可以得出結論:Python在終止時總是完成寫操作,並且不會將文件保留在中間狀態中?還是這取決於操作系統和文件系統(我正在測試Linux和ext4分區)?

回答

1

這並不是文件如何被「清理」,而是如何寫入文件。一個程序可能會爲單個「塊」數據(行或其他)執行多次寫入操作,並且在這個過程當中可能會中斷,並最終導致寫入部分記錄。

查看csv模塊的C source,它將每行組裝成一個字符串緩衝區,然後使用一個write()調用寫入該行。這通常應該是安全的;要麼將行傳遞給操作系統,要麼不行,如果它到達操作系統,它將全部被寫入或不是(當然,除了硬件問題,其中的一部分可能會進入壞扇區)。

作者對象是一個Python對象,並且自定義作家可以在其write()中做一些奇怪的事情,這可能會破壞這一點,但假設它是一個普通的文件對象,它應該沒問題。

相關問題