今天有同學問,用os模組的access()能否判斷一個檔案是否被佔用?直覺上,這是行不通的,因為access()返回的是檔案的讀寫屬性。為了確認這一點,我簡單測試了一下。
>>> import os>>> fn = r'D:\temp\csdn\t.py' # 測試用的檔案>>> os.access(fn, os.F_OK) # 檔案是否存在True>>> os.access(fn, os.R_OK) # 檔案是否可讀True>>> os.access(fn, os.W_OK) # 檔案是否可寫True>>> os.access(fn, os.X_OK) # 檔案是否可執行True>>> fp = open(fn, 'a+') # 以追加寫的方式開啟檔案>>> os.access(fn, os.F_OK) # 檔案當然還在True>>> os.access(fn, os.R_OK) # 檔案依然可讀True>>> os.access(fn, os.W_OK) # 檔案依然可寫True>>> os.access(fn, os.X_OK) # 檔案依然執行True>>> fp.close()
可見,os.access()返回的是檔案讀寫屬性,與檔案是否被佔用沒有半毛錢關係。
後來,群裡有同學建議說,不妨用try嘗試著open檔案,如果成功,表示檔案沒有被佔用,如果丟擲異常,則表示檔案被佔用。果真如此嗎?還是用程式碼驗證一下吧。
>>> fp1 = open(fn, 'a+')>>> fp2 = open(fn, 'a+')>>> fp1.close()>>> fp2.close()
結果表明,對同一個檔案以寫的方式開啟多次,系統並沒有丟擲異常。為什麼會這樣呢?究其原因,是因為檔案被開啟和檔案被佔用是兩個完全不同的問題。順便提醒一下,做上面的測試時,不要使用’w’的方式,否則檔案內容會被清空。
那麼,究竟應該如何用Python判斷一個檔案是否被佔用呢?這個問題還是要回歸到作業系統層面來解決,也就是依賴win32api模組。
>>> import win32file>>> def is_used(file_name): try: vHandle = win32file.CreateFile(file_name, win32file.GENERIC_READ, 0, None, win32file.OPEN_EXISTING, win32file.FILE_ATTRIBUTE_NORMAL, None) return int(vHandle) == win32file.INVALID_HANDLE_VALUE except: return True finally: try: win32file.CloseHandle(vHandle) except: pass >>> fn = r'D:\temp\csdn\t.py'>>> is_used(fn)False>>> fp = open(fn, 'a+')>>> is_used(fn)True>>> fp.close()>>> is_used(fn)False
簡單驗證了一下,函式is_used()基本可用。