2012-10-02 69 views
14

是否有可能检查文件是否已被删除或在python中重新创建?检查打开的文件是否在python中打开后被删除

例如,如果您在脚本中执行了open("file"),然后当该文件仍处于打开状态时,您执行rm file; touch file;,那么即使该文件已被删除,该脚本仍会保留对旧文件的引用。

+0

也许os.path.exists工作? – Alex

+2

os.path.exists的问题在于,即使旧文件已被删除,也可能存在具有相同路径名的另一个文件 – user1502906

回答

4

是的。使用the os.stat() function检查文件长度。如果长度为零(或者函数返回错误“File not found”),则有人删除该文件。

或者,您可以在每次需要写入文件时打开+写入+关闭文件。缺点是打开一个文件是一个非常慢的操作,所以如果你需要编写大量的数据,这是不成问题的。

为什么?因为新文件不是您打开的文件。简而言之,Unix文件系统有两个层次。一个是目录条目(即文件名,文件大小,修改时间,指向数据的指针),第二个层次是文件数据。

当您打开一个文件时,Unix使用该名称来查找文件数据。之后,它只在第二级上运行 - 对目录条目的更改对任何打开的“文件句柄”都没有影响。这正是您可以删除目录条目的原因:您的程序没有使用它。

当您使用os.stat()时,您不再查看文件数据,而是再次查看目录条目。

从积极的方面来看,这允许您创建除了您的程序之外无法看到的文件:打开文件,删除它然后使用它。由于文件没有目录项,因此其他程序不能访问数据。

在消极的一面,你不能轻易解决你所拥有的问题。

+1

在Linux上,您可以查看“proc//fd/...”并访问即使文件被删除也是如此。如果你想从YouTube上下载一个视频的副本,这有时会派上用场;-) – hochl

+0

谢谢,我知道它与stat有关 – user1502906

+0

@hochl:有趣。注意:要读取进程的'fd'目录的内容,您需要是该用户或root用户(权限为'dr-x ------'),因此它仍然是安全的。 –

3

是 - 您可以使用inotify工具来检查文件更改等。它也有一个Python binding。使用inotify你可以看文件系统活动的文件或目录。从手册中可以发现以下事件:

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

从这里你可以谷歌自己的解决方案,但我认为你得到的整体思路。当然,这可能只适用于Linux,但从你的问题,我假设你正在使用它(参考rmtouch)。

14

您应该为fstat打开文件的文件描述符。

>>> 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 

好吧,这个文件有一个链接,所以在文件系统中有一个名字。现在将其删除:

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

没有更多的联系,所以我们有一个“匿名文件”,这只是kept alive as long as we have it open。创建具有相同名称的新文件上的旧文件没有影响:

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

当然,st_nlink有时可>1开始,所以检查零也不是完全可靠的(尽管在受控环境中,可能会足够好)。相反,你可以验证在你初次打开路径的文件是否是你通过比较stat结果有一个文件描述符同一个:

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

(如果你想这是100%正确的,那么你应该在这种情况下,仅比较上stat结果st_devst_ino领域,因为其他领域,尤其是st_atime可能调用之间改变)。