1

简短版本:我编写/改编的 Python 脚本,用于在修改文件时监视目录的更改触发两次。为什么?

长版:

我正在编写一些 Python 代码来监视目录及其子目录的更改。

我从http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html的“使用 ReadDirectoryChanges API”部分中的示例开始

(出于企业 IT 的原因,我不适合使用 Python Watchdog 包。)

从那里的例子中剪切和粘贴:

import os

import win32file
import win32con

ACTIONS = {
  1 : "Created",
  2 : "Deleted",
  3 : "Updated",
  4 : "Renamed from something",
  5 : "Renamed to something"
}
# Thanks to Claudio Grondi for the correct set of numbers
FILE_LIST_DIRECTORY = 0x0001

path_to_watch = "."
hDir = win32file.CreateFile (
  path_to_watch,
  FILE_LIST_DIRECTORY,
  win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
  None,
  win32con.OPEN_EXISTING,
  win32con.FILE_FLAG_BACKUP_SEMANTICS,
  None
)
while 1:
  #
  # ReadDirectoryChangesW takes a previously-created
  # handle to a directory, a buffer size for results,
  # a flag to indicate whether to watch subtrees and
  # a filter of what changes to notify.
  #
  # NB Tim Juchcinski reports that he needed to up
  # the buffer size to be sure of picking up all
  # events when a large number of files were
  # deleted at once.
  #
  results = win32file.ReadDirectoryChangesW (
    hDir,
    1024,
    True,
    win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
     win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
     win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
     win32con.FILE_NOTIFY_CHANGE_SIZE |
     win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
     win32con.FILE_NOTIFY_CHANGE_SECURITY,
    None,
    None
  )
  for action, file in results:
    full_filename = os.path.join (path_to_watch, file)
    print full_filename, ACTIONS.get (action, "Unknown")

一般来说,这个例子工作正常,做我想做的事。特别是,它在创建文件时工作正常。然而,当一个文件被编辑/修改/更新时,最后的打印语句(代表我真正想做的动作)会触发两次。

为什么会这样?以及如何防止它,或者至少解决它?我有过的最好的想法是第一次为 True 而第二次为 False 的标志。然而,这感觉就像一个杂牌。

关于一个可能相关的问题,我在哪里可以找到有关 win32con 包和 Microsoft ReadDirectoryChanges API 的文档?我做了一些谷歌搜索,但没有发现任何我认为有用的东西。

哦,是的 - 我在 Windows 7 Enterprise 上运行 Python 3.5.1。

编辑:好的,看起来我所看到的可能是 ReadDirectoryChangesW() 所固有的。我发现这个 StackOverflow 线程似乎基本上是相同的问题,除了原始海报使用的是 C++,而不是 Python。C++ WinApi:ReadDirectoryChangesW() 接收双重通知

4

1 回答 1

2

我没有安装 python 2.7,所以我无法通过查看这部分来测试自己

 win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
 win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
 win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
 win32con.FILE_NOTIFY_CHANGE_SIZE | #this will change when someone writes or deletes to the file
 win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |#this will change when someone modifies the file
 win32con.FILE_NOTIFY_CHANGE_SECURITY,

看看这两个条件是如何被同一个动作触发的?这可能是触发您行为的原因,请尝试删除两者之一

编辑以澄清以下评论:

为了了解每种更改类型的行为,请尝试以下操作:

results = {}
results['FName_Change'] = win32file.ReadDirectoryChangesW (
                        hDir,
                        1024,
                        True,
                        win32con.FILE_NOTIFY_CHANGE_FILE_NAME,
                        None,
                        None
                      )
results['DName_Change'] = win32file.ReadDirectoryChangesW (
                        hDir,
                        1024,
                        True,
                         win32con.FILE_NOTIFY_CHANGE_DIR_NAME, 
                        None,
                        None
                        )
  results['Attributes_Change'] = win32file.ReadDirectoryChangesW (
                        hDir,
                        1024,
                        True,
                         win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES, 
                        None,
                        None

通过操纵此数据结构,您应该能够从更改中提取行为类型信息

于 2018-11-06T13:36:11.130 回答