2012-10-02 13 views
14

Czy można sprawdzić, czy plik został usunięty lub odtworzony w pythonie?Sprawdź, czy otwarty plik został usunięty po otwarciu w pythonie

Na przykład, jeśli zrobił open("file") w skrypcie, a następnie podczas gdy plik jest nadal otwarty, robisz rm file; touch file;, następnie skrypt nadal posiadają odniesienie do starego pliku, mimo że została już usunięta.

+0

może os.path.exists pracę w tym przypadku? – Alex

+2

Problem z os.path.exists polega na tym, że może istnieć inny plik o tej samej nazwie ścieżki, mimo że stary plik został już usunięty. – user1502906

Odpowiedz

4

Tak. Użyj opcji the os.stat() function, aby sprawdzić długość pliku. Jeśli długość wynosi zero (lub funkcja zwraca błąd "File not found"), to ktoś usunął plik.

Alternatywnie można otworzyć + napisać + zamknąć plik za każdym razem, gdy trzeba coś do niego napisać. Wadą jest to, że otwieranie pliku jest dość powolną operacją, więc nie jest to możliwe, jeśli trzeba napisać dużo danych.

Dlaczego? Ponieważ nowy plik nie jest plikiem, który trzymasz otwarty. W skrócie, systemy plików Unix mają dwa poziomy. Jednym z nich jest pozycja katalogu (tj. Nazwa pliku, rozmiar pliku, czas modyfikacji, wskaźnik do danych), a drugi poziom to dane pliku.

Po otwarciu pliku system Unix używa nazwy, aby znaleźć dane pliku. Następnie działa tylko na drugim poziomie - zmiany w pozycji katalogu nie mają wpływu na żadne otwarte "uchwyty plików". Właśnie dlatego możesz usunąć wpis w katalogu: Twój program go nie używa.

Podczas korzystania z os.stat(), nie patrzysz na dane pliku, ale ponownie na pozycję katalogu.

Po stronie pozytywów, pozwala to na tworzenie plików, których nikt nie może zobaczyć, ale Twój program: Otwórz plik, usuń go, a następnie użyj. Ponieważ nie istnieje pozycja katalogu dla pliku, żaden inny program nie może uzyskać dostępu do danych.

Po stronie negatywów, nie można łatwo rozwiązać problemów, takich jak ten, który masz.

+1

W systemie Linux możesz zajrzeć do 'proc//fd/...' i uzyskać dostęp do dane, nawet jeśli plik został usunięty. Czasami przydaje się to, jeśli chcesz zrobić kopię pobieranego pliku wideo z youtube ;-) – hochl

+0

dzięki, wiedziałem, że to ma coś wspólnego ze statem – user1502906

+0

@hochl: Interesujące. Uwaga: Aby odczytać zawartość katalogu 'fd' procesu, musisz być tym użytkownikiem lub root (uprawnienia to' dr-x ------ '), więc nadal jest bezpieczny. –

3

Tak - można użyć funkcji inotify, aby sprawdzić, czy zmiany w plikach i inne. Istnieje również Python binding. Korzystając z inotify, możesz oglądać pliki lub katalogi dotyczące działania systemu plików. Z podręcznika można wykryć następujące zdarzenia:

IN_ACCESS   File was accessed (read) (*). 
IN_ATTRIB   Metadata changed, e.g., permissions, timestamps, extended attributes, link count (since Linux 2.6.25), UID, GID, etc. (*). 
IN_CLOSE_WRITE File opened for writing was closed (*). 
IN_CLOSE_NOWRITE File not opened for writing was closed (*). 
IN_CREATE   File/directory created in watched directory (*). 
IN_DELETE   File/directory deleted from watched directory (*). 
IN_DELETE_SELF Watched file/directory was itself deleted. 
IN_MODIFY   File was modified (*). 
IN_MOVE_SELF  Watched file/directory was itself moved. 
IN_MOVED_FROM  File moved out of watched directory (*). 
IN_MOVED_TO  File moved into watched directory (*). 
IN_OPEN   File was opened (*). 

Stąd możesz samemu znaleźć rozwiązanie Google, ale myślę, że masz ogólny pomysł. Oczywiście może to działać tylko na Linuksie, ale z twojego pytania zakładam, że go używasz (odniesienia do rm i touch).

14

Powinieneś wpisać fstat deskryptor pliku dla otwartego pliku.

>>> import os 
>>> f = open("testdv.py") 
>>> os.fstat(f.fileno()) 
posix.stat_result(st_mode=33188, st_ino=1508053, st_dev=65027L, st_nlink=1, st_uid=1000, st_gid=1000, st_size=1107, st_atime=1349180541, st_mtime=1349180540, st_ctime=1349180540) 
>>> os.fstat(f.fileno()).st_nlink 
1 

Ok, ten plik ma jeden link, więc jeden nazwę w systemie plików. Teraz usunąć go:

>>> os.unlink("testdv.py") 
>>> os.fstat(f.fileno()).st_nlink 
0 

Nie więcej linków, więc mamy „anonimowy plik” to tylko kept alive as long as we have it open. Tworzenie nowego pliku o tej samej nazwie nie ma wpływu na starym pliku:

>>> g = open("testdv.py", "w") 
>>> os.fstat(g.fileno()).st_nlink 
1 
>>> os.fstat(f.fileno()).st_nlink 
0 

Oczywiście st_nlink może być czasem >1 początkowo, więc sprawdzenie, czy do zera nie jest całkowicie niezawodny (choć w kontrolowanych warunkach, to może być wystarczająco dobry).Zamiast tego, można sprawdzić, czy plik na ścieżce, którą początkowo otwarty jest ten sam, który masz deskryptor dla porównując stat wyniki:

>>> os.stat("testdv.py") == os.fstat(f.fileno()) 
False 
>>> os.stat("testdv.py") == os.fstat(g.fileno()) 
True 

(A jeśli chcesz to być w 100% poprawne, a następnie należy porównać tylko st_dev i st_ino pola na stat wyników, ponieważ pozostałe pola i st_atime w szczególności może zmieniać się pomiędzy połączeniami.)