如何在python中获取文件关闭事件

时间:2014-03-14 13:25:34

标签: python windows file process file-monitoring

在Windows 7 64位计算机上使用python 2.7。

如何获取文件关闭事件:

  1. 在文件打开的新进程中打开文件时(如记事本,每次在wordpad的新进程中打开文件的wordpad)
  2. 在文件打开器的选项卡中打开文件时(如记事本++,它会打开新选项卡中的所有文件,但只存在一个记事本++运行的过程)
  3. 那么,在上述情况下如何获取文件关闭事件?是否可以通过公共代码实现上述情况?我正在处理不同的文件类型

4 个答案:

答案 0 :(得分:16)

对于* nix系统来说,事实证明这是一项非常简单的任务,但在Windows上,获取文件关闭事件并不是一项简单的任务。请阅读以下按OS' es。

分组的常用方法摘要

对于Linux

在Linux上,可以轻松监控文件系统更改,并且非常详细。最好的工具是名为inotify的内核功能,并且有一个使用它的Python实现,称为Pynotify。

  • Pynotify

    Pyinotify是一个用于监视文件系统更改的Python模块。 Pyinotify依赖于一个名为inotify的Linux内核功能(在内核2.6.13中合并),它是一个事件驱动的通知程序。其通知通过三个系统调用从内核空间导出到用户空间。 Pyinotify绑定这些系统调用,并在它们之上提供一个实现,提供一种通用和抽象的方式来操作这些功能。

    Here您可以找到可以使用Pynotify监控的事件列表。

    使用示例:

    导入pyinotify

    class EventHandler(pyinotify.ProcessEvent):
        def process_IN_CLOSE_NOWRITE(self, event):
            print "File was closed without writing: " + event.pathname
        def process_IN_CLOSE_WRITE(self, event):
            print "File was closed with writing: " + event.pathname
    
    def watch(filename):
        wm = pyinotify.WatchManager()
        mask = pyinotify.IN_CLOSE_NOWRITE | pyinotify.IN_CLOSE_WRITE
        wm.add_watch(filename, mask)
    
        eh = EventHandler()
        notifier = pyinotify.Notifier(wm, eh)
        notifier.loop()
    
    if __name__ == '__main__':
        watch('/path/to/file')
    

对于Windows

Windows的情况比Linux复杂得多。大多数库依赖ReadDirectoryChanges API,这是受限制的,无法检测文件关闭事件等更精细的细节。然而,还有其他方法可以检测此类事件,请继续阅读以了解更多信息。

  • Watcher

    注意: Watcher最后一次更新于2011年2月,所以跳过这个可能是安全的。

    Watcher是一个低级C扩展程序,用于在Windows系统上使用ReadDirectoryChangesW API接收文件系统更新。该软件包还包括一个高级接口,用于模拟大多数.NET FileSystemWatcher API 与Watcher一起检测文件关闭事件的最近者可以监视FILE_NOTIFY_CHANGE_LAST_WRITE和/或FILE_NOTIFY_CHANGE_LAST_ACCESS事件。

    使用示例:

    import watcher
    w = watcher.Watcher(dir, callback)
    w.flags = watcher.FILE_NOTIFY_CHANGE_LAST_WRITE
    w.start()
    
  • Watchdog

    Python API和shell实用程序,用于监视文件系统事件。易于安装:$ pip install watchdog。有关详细信息,请访问documentation Windows上的Watchdog依赖于ReadDirectoryChangesW API,它会像Watcher和其他依赖相同API的库一样引起注意。

  • Pywatch

    Linux watch命令的python near-clone。可以告诉pywatch.watcher.Watcher类监视一组文件,并在任何这些文件发生更改时给出一组命令来运行。它只能监视文件更改事件,因为它依赖于轮询stat's st_mtime

使用NTFS的Windows奖金:

  • NTFS USN Journal

    NTFS USN(更新序列号)日志是NTFS的一项功能,它保留对卷所做更改的记录。它被列为 Bonus 的原因是因为与其他条目不同,它不是特定的库,而是NTFS系统上存在的特性。因此,如果您使用其他Windows文件系统(如FAT,ReFS等),则不适用 它的工作方式是系统记录USN Journal文件中对卷所做的所有更改,每个卷都有自己的实例。 “更改日志”中的每条记录都包含USN,文件名以及有关更改内容的信息。

    此方法对此问题感兴趣的主要原因是,与大多数其他方法不同,此方法提供了一种检测文件关闭事件的方法,定义为 USN_REASON_CLOSE 。有关完整事件列表的更多信息,请参阅此MSDN article。有关USN日记功能的完整文档,请访问此MSDN page

    有多种方法可以从Python访问USN Journal,但唯一成熟的选项似乎是 ntfsjournal 模块。

"适当"适用于Windows的方式:

  • File system filter driver

    正如MSDN page所述:

      

    文件系统过滤器驱动程序是一个可添加值的可选驱动程序   或修改文件系统的行为。文件系统筛选器驱动程序   是一个内核模式组件,作为Windows执行程序的一部分运行。   文件系统筛选器驱动程序可以筛选一个或多个I / O操作   文件系统或文件系统卷。取决于性质   驱动程序,过滤器可能意味着记录,观察,修改甚至阻止。典型   文件系统筛选器驱动程序的应用程序包括防病毒   实用程序,加密程序和分层存储管理   系统

    实现文件系统过滤器驱动程序并不是一件容易的事,但对于想尝试一下的人来说,有一个很好的介绍教程CodeProject

    P.S。请查看@ixe013's answer以获取有关此方法的其他信息。

  • Qt's QFileSystemWatcher

    QFileSystemWatcher类提供了一个用于监视文件和目录以进行修改的接口。这个课程在Qt 4.2中介绍 不幸的是,它的功能相当有限,因为它只能检测文件何时被修改,重命名或删除,以及何时将新文件添加到目录中。

    使用示例:

    import sys
    from PyQt4 import QtCore
    
    def directory_changed(path):
        print('Directory Changed: %s' % path)
    
    def file_changed(path):
        print('File Changed: %s' % path)
    
    app = QtCore.QCoreApplication(sys.argv)
    
    paths = ['/path/to/file']
    fs_watcher = QtCore.QFileSystemWatcher(paths)
    fs_watcher.directoryChanged.connect(directory_changed)
    fs_watcher.fileChanged.connect(file_changed)
    
    app.exec_()
    

答案 1 :(得分:3)

您面临的问题不是Python,而是Windows。它可以完成,但你必须为它编写一些非trival C / C ++代码。

Windows上的userland中不存在文件打开或文件关闭用户模式通知。这就是为什么其他人建议的图书馆没有文件关闭通知的原因。在Windows中,用于检测用户空间更改的API为ReadDirectoryChangesW。它会提醒您one of the following notifications

  • FILE_ACTION_ADDED如果文件已添加到目录中。
  • FILE_ACTION_REMOVED如果文件已从目录中删除。
  • FILE_ACTION_MODIFIED如果文件被修改。这可以是时间戳或属性的更改。
  • FILE_ACTION_RENAMED_OLD_NAME如果文件已重命名且这是旧名称。
  • FILE_ACTION_RENAMED_NEW_NAME如果文件已重命名且这是新名称。

没有多少Python可以改变Windows为您提供的功能。

要获取文件关闭通知,tools like Process Monitor安装Minifilter that lives in the kernel,靠近EFS等其他过滤器的顶部。

要获得你想要的东西,你需要:

  1. 安装一个Minifilter,其中包含将事件发送回userland的代码。使用Microsoft's Minispy sample,它稳定而快速。
  2. 转换user程序中的代码,使其成为Python扩展(minispy.pyd),公开生成事件的生成器。这是困难的部分,我会回过头来看。
  3. 你必须过滤掉事件,你不会忘记在闲置的Windows机器上IO的数量!
  4. 然后,您的Python程序可以导入您的扩展程序并执行其操作。
  5. 整件事看起来像这样:

    A Python wrapper over a Windows Minifilter for filesystem events

    当然你可以将EFS超过NTFS,这只是为了表明你的微过滤器将超越所有。

    困难的部分:

    • 您的微过滤器必须由Microsoft信任的权威机构进行数字签名。想到了Verising,但还有其他人。
    • 调试需要单独的(虚拟)计算机,但您可以轻松地模拟界面。
    • 您需要使用具有管理员权限的帐户安装minifilter。任何用户都可以阅读活动。
    • 您将不得不与自己的多用户打交道。许多用户只有一个微过滤器。
    • 您必须将用户程序从MiniSpy示例转换为DLL,您将使用Python扩展包装。

    最后两个是最难的。

答案 2 :(得分:1)

您可以使用Pyfanotyfibutter

我认为您会发现此链接非常有用:Linux file system events with C, Python and Ruby

在那里你会找到一个关于做你想做的事情的例子(使用pyinotify)这是代码:

import pyinotify

DIR_TO_WATCH="/tmp/notify-dir"
FILE_TO_WATCH="/tmp/notify-dir/notify-file.txt"

wm = pyinotify.WatchManager()

dir_events = pyinotify.IN_DELETE | pyinotify.IN_CREATE
file_events = pyinotify.IN_OPEN | pyinotify.IN_CLOSE_WRITE | pyinotify.IN_CLOSE_NOWRITE

class EventHandler(pyinotify.ProcessEvent):
    def process_IN_DELETE(self, event):
        print("File %s was deleted" % event.pathname) #python 3 style print function
    def process_IN_CREATE(self, event):
        print("File %s was created" % event.pathname)
    def process_IN_OPEN(self, event):
        print("File %s was opened" % event.pathname)
    def process_IN_CLOSE_WRITE(self, event):
        print("File %s was closed after writing" % event.pathname)
    def process_IN_CLOSE_NOWRITE(self, event):
        print("File %s was closed after reading" % event.pathname)

event_handler = EventHandler()
notifier = pyinotify.Notifier(wm, event_handler)

wm.add_watch(DIR_TO_WATCH, dir_events)
wm.add_watch(FILE_TO_WATCH, file_events)

notifier.loop()

答案 3 :(得分:0)

我还没有找到在Windows上捕获openclose事件的程序包。正如其他人所提到的,pyinotify是基于Linux的操作系统的绝佳选择。

由于我无法观看已结束的活动,因此我选择了修改后的活动。事实上,这是一个非常重要的事情。解决方案的类型(即,在我看到文件关闭之前,我无法暂停)。但是,这种方法效果出奇的好。

我已经使用了watchdog套餐。下面的代码来自他们的sample实现,如果您没有在命令行上传递路径,则会监视当前目录,否则它会监视您传递的路径。

示例通话:python test.pypython test.py C:\Users\Administrator\Desktop

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    event_handler = LoggingEventHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join() 

此代码将显示何时创建,修改,删除或重命名/移动文件。您只需观看on_modified event即可进行过滤。