2012-10-02 38 views
14

Có thể kiểm tra xem tệp đã bị xóa hoặc tạo lại trong python không?Kiểm tra xem tệp mở đã bị xóa sau khi mở trong python

Ví dụ: nếu bạn đã thực hiện open("file") trong tập lệnh và sau đó trong khi tệp đó vẫn mở, bạn làm rm file; touch file;, thì tập lệnh sẽ vẫn giữ tham chiếu đến tệp cũ mặc dù tệp đã bị xóa.

+0

có thể os.path.exists hoạt động trong trường hợp này? – Alex

+2

vấn đề với os.path.exists là một tệp khác có cùng tên đường dẫn có thể tồn tại, mặc dù tệp cũ đã bị xóa – user1502906

Trả lời

4

Có. Sử dụng the os.stat() function để kiểm tra độ dài tệp. Nếu độ dài bằng không (hoặc hàm trả về lỗi "Không tìm thấy tệp"), thì ai đó đã xóa tệp.

Hoặc, bạn có thể mở + ghi + đóng tệp mỗi lần bạn cần viết nội dung nào đó vào đó. Hạn chế là việc mở một tập tin là một hoạt động khá chậm, vì vậy đây là câu hỏi nếu bạn cần viết nhiều dữ liệu.

Tại sao? Vì tệp mới không phải là tệp mà bạn đang mở. Tóm lại, các hệ thống tập tin Unix có hai cấp độ. Một là mục nhập thư mục (ví dụ: tên tệp, kích thước tệp, thời gian sửa đổi, con trỏ đến dữ liệu) và cấp thứ hai là dữ liệu tệp.

Khi bạn mở tệp, Unix sử dụng tên để tìm dữ liệu tệp. Sau đó, nó chỉ hoạt động ở cấp độ thứ hai - những thay đổi đối với mục nhập thư mục không ảnh hưởng đến bất kỳ "tệp xử lý" mở nào. Đó chính là lý do tại sao bạn có thể xóa mục nhập thư mục: Chương trình của bạn không sử dụng nó.

Khi bạn sử dụng os.stat(), bạn không nhìn vào dữ liệu tệp nhưng lại ở mục nhập thư mục.

Về mặt tích cực, điều này cho phép bạn tạo tệp mà không ai có thể xem nhưng chương trình của bạn: Mở tệp, xóa tệp và sau đó sử dụng tệp. Vì không có mục nhập thư mục nào cho tệp, nên không có chương trình nào khác có thể truy cập dữ liệu.

Ở mặt phủ định, bạn không thể dễ dàng giải quyết các vấn đề như vấn đề bạn gặp phải.

+1

Trên Linux, bạn có thể xem xét 'proc//fd/... 'và truy cập dữ liệu ngay cả khi tệp đã bị xóa. Điều đó đôi khi có ích nếu bạn muốn tạo một bản sao của video mà bạn đang tải xuống từ youtube ;-) – hochl

+0

cảm ơn, tôi biết nó có liên quan đến stat – user1502906

+0

@hochl: Thú vị. Lưu ý: Để đọc nội dung của thư mục 'fd' của một tiến trình, bạn cần phải là người dùng hoặc root đó (các quyền là' dr-x ------ '), vì vậy nó vẫn an toàn. –

3

Có - bạn có thể sử dụng cơ sở inotify để kiểm tra các thay đổi về tệp và hơn thế nữa. Ngoài ra còn có một Python binding cho nó. Sử dụng inotify bạn có thể xem các tập tin hoặc thư mục cho activiy hệ thống tập tin. Từ hướng dẫn sử dụng, các sự kiện sau có thể được phát hiện:

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 (*). 

Từ đây bạn có thể tự giải pháp cho mình, nhưng tôi nghĩ bạn sẽ có được ý tưởng tổng thể. Tất nhiên điều này chỉ có thể hoạt động trên Linux, nhưng từ câu hỏi của bạn, tôi cho rằng bạn đang sử dụng nó (tham chiếu đến rmtouch).

14

Bạn nên fstat bộ mô tả tệp cho tệp đã mở.

>>> 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, tệp này có một liên kết, do đó, một tên trong hệ thống tệp. Bây giờ hãy xóa nó:

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

Không có liên kết nào khác, vì vậy chúng tôi có "tệp ẩn danh" chỉ kept alive as long as we have it open. Tạo một file mới với tên tương tự đã không ảnh hưởng đến các tập tin cũ:

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

Tất nhiên, st_nlink đôi khi có thể >1 ban đầu, vì vậy kiểm tra rằng cho zero là không hoàn toàn đáng tin cậy (mặc dù trong một khung cảnh được kiểm soát, nó có thể đủ tốt).Thay vào đó, bạn có thể xác minh xem các tập tin vào con đường bạn bước đầu mở ra là một tương tự mà bạn có một bộ mô tả tập tin cho bằng cách so sánh stat kết quả:

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

(Và nếu bạn muốn điều này là chính xác 100%, sau đó bạn chỉ nên so sánh các trường st_devst_ino trên stat kết quả, vì các trường khác và st_atime nói riêng có thể thay đổi giữa các cuộc gọi.)

Các vấn đề liên quan