Короткая версия:
Сценарий Python, который я написал / адаптировал для отслеживания изменений в каталоге, запускается дважды при изменении файла. Почему?
Длинная версия:
Я пишу некоторый код Python для отслеживания изменений в каталоге и его подкаталогах.
Я начинаю с примера, найденного в разделе «Использование API ReadDirectoryChanges» http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html
(По корпоративным ИТ-причинам использование пакета 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")
В общем, этот пример работает нормально и делает то, что я хочу. В частности, он прекрасно работает при создании файла. Однако, когда файл редактируется / изменяется / обновляется, оператор print в конце (который заменяет действие, которое я действительно хочу выполнить) срабатывает дважды.
Почему это происходит? И как это можно предотвратить или хотя бы обойти? Лучшая идея, которая у меня была, - это флаг, который в первый раз является истинным, а второй - ложным. Тем не менее, это похоже на клудж.
В случае возможной связанной проблемы, где я могу найти документацию по пакету win32con и API-интерфейсу Microsoft ReadDirectoryChanges? Я немного погуглил, но не нашел ничего, что считаю полезным.
О да, я использую Python 3.5.1 в Windows 7 Enterprise.
EDIT:
Хорошо, похоже, что то, что я вижу, может быть присуще ReadDirectoryChangesW (). Я обнаружил этот поток StackOverflow, который, кажется, в основном та же проблема, за исключением того, что оригинальный постер использует C ++, а не Python. C ++ WinApi: ReadDirectoryChangesW () Получение двойных уведомлений