早上好,
我遇到了一个我在Python中创建的程序的一个特殊问题。看来,当我将文件从一个位置拖放到另一个位置时,并非所有文件都被模块注册为事件。
我一直在使用win32file和win32con来尝试获取与将文件从一个位置移动到另一个位置以进行处理相关的所有事件。
这是我的检测代码的一小部分:
import win32file
import win32con
def main():
path_to_watch = 'D:\\'
_file_list_dir = 1
# Create a watcher handle
_h_dir = win32file.CreateFile(
path_to_watch,
_file_list_dir,
win32con.FILE_SHARE_READ |
win32con.FILE_SHARE_WRITE |
win32con.FILE_SHARE_DELETE,
None,
win32con.OPEN_EXISTING,
win32con.FILE_FLAG_BACKUP_SEMANTICS,
None
)
while 1:
results = win32file.ReadDirectoryChangesW(
_h_dir,
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:
if _action == 1:
print 'found!'
if _action == 2:
print 'deleted!'
我拖放了7个文件,它只发现了4个。
# found!
# found!
# found!
# found!
如何检测所有丢弃的文件?
[ActiveState.Docs]: win32file.ReadDirectoryChangesW(这是我能为[GitHub]: mhammond/pywin32 - Python for Windows (pywin32) Extensions找到的最好的文档)是[MS.Docs]: ReadDirectoryChangesW function的包装。这是它所说的(关于缓冲区):
无论如何,我拿了你的代码并“改变了一下”。
code.朋友:
import sys
import msvcrt
import pywintypes
import win32file
import win32con
import win32api
import win32event
FILE_LIST_DIRECTORY = 0x0001
FILE_ACTION_ADDED = 0x00000001
FILE_ACTION_REMOVED = 0x00000002
ASYNC_TIMEOUT = 5000
BUF_SIZE = 65536
def get_dir_handle(dir_name, async):
flags_and_attributes = win32con.FILE_FLAG_BACKUP_SEMANTICS
if async:
flags_and_attributes |= win32con.FILE_FLAG_OVERLAPPED
dir_handle = win32file.CreateFile(
dir_name,
FILE_LIST_DIRECTORY,
(win32con.FILE_SHARE_READ |
win32con.FILE_SHARE_WRITE |
win32con.FILE_SHARE_DELETE),
None,
win32con.OPEN_EXISTING,
flags_and_attributes,
None
)
return dir_handle
def read_dir_changes(dir_handle, size_or_buf, overlapped):
return win32file.ReadDirectoryChangesW(
dir_handle,
size_or_buf,
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),
overlapped,
None
)
def handle_results(results):
for item in results:
print(" {} {:d}".format(item, len(item[1])))
_action, _ = item
if _action == FILE_ACTION_ADDED:
print(" found!")
if _action == FILE_ACTION_REMOVED:
print(" deleted!")
def esc_pressed():
return msvcrt.kbhit() and ord(msvcrt.getch()) == 27
def monitor_dir_sync(dir_handle):
idx = 0
while True:
print("Index: {:d}".format(idx))
idx += 1
results = read_dir_changes(dir_handle, BUF_SIZE, None)
handle_results(results)
if esc_pressed():
break
def monitor_dir_async(dir_handle):
idx = 0
buffer = win32file.AllocateReadBuffer(BUF_SIZE)
overlapped = pywintypes.OVERLAPPED()
overlapped.hEvent = win32event.CreateEvent(None, False, 0, None)
while True:
print("Index: {:d}".format(idx))
idx += 1
read_dir_changes(dir_handle, buffer, overlapped)
rc = win32event.WaitForSingleObject(overlapped.hEvent, ASYNC_TIMEOUT)
if rc == win32event.WAIT_OBJECT_0:
bufer_size = win32file.GetOverlappedResult(dir_handle, overlapped, True)
results = win32file.FILE_NOTIFY_INFORMATION(buffer, bufer_size)
handle_results(results)
elif rc == win32event.WAIT_TIMEOUT:
#print(" timeout...")
pass
else:
print("Received {:d}. Exiting".format(rc))
break
if esc_pressed():
break
win32api.CloseHandle(overlapped.hEvent)
def monitor_dir(dir_name, async=False):
dir_handle = get_dir_handle(dir_name, async)
if async:
monitor_dir_async(dir_handle)
else:
monitor_dir_sync(dir_handle)
win32api.CloseHandle(dir_handle)
def main():
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
async = True
print("Attempting {}ynchronous mode using a buffer {:d} bytes long...".format("As" if async else "S", BUF_SIZE))
monitor_dir(".\\test", async=async)
if __name__ == "__main__":
main()
笔记:
输出:
e:\Work\Dev\StackOverflow\q049799109>dir /b test 0123456789.txt 01234567890123456789.txt 012345678901234567890123456789.txt 0123456789012345678901234567890123456789.txt 01234567890123456789012345678901234567890123456789.txt 012345678901234567890123456789012345678901234567890123456789.txt 0123456789012345678901234567890123456789012345678901234567890123456789.txt 01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt e:\Work\Dev\StackOverflow\q049799109> e:\Work\Dev\StackOverflow\q049799109>"C:\Install\x64\HPE\OPSWpython\2.7.10__00\python.exe" code.py Python 2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)] on win32 Attempting Synchronous mode using a buffer 512 bytes long... Index: 0 (2, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 deleted! Index: 1 (2, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 deleted! Index: 2 (2, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 deleted! Index: 3 (2, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 deleted! (2, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 deleted! Index: 4 (2, u'01234567890123456789012345678901234567890123456789.txt') 54 deleted! Index: 5 (2, u'0123456789012345678901234567890123456789.txt') 44 deleted! (2, u'012345678901234567890123456789.txt') 34 deleted! Index: 6 (2, u'01234567890123456789.txt') 24 deleted! (2, u'0123456789.txt') 14 deleted! Index: 7 (1, u'0123456789.txt') 14 found! Index: 8 (3, u'0123456789.txt') 14 Index: 9 (1, u'01234567890123456789.txt') 24 found! Index: 10 (3, u'01234567890123456789.txt') 24 (1, u'012345678901234567890123456789.txt') 34 found! (3, u'012345678901234567890123456789.txt') 34 (1, u'0123456789012345678901234567890123456789.txt') 44 found! Index: 11 (3, u'0123456789012345678901234567890123456789.txt') 44 (1, u'01234567890123456789012345678901234567890123456789.txt') 54 found! (3, u'01234567890123456789012345678901234567890123456789.txt') 54 Index: 12 Index: 13 (1, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 found! Index: 14 Index: 15 (1, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 found! Index: 16 (3, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 Index: 17 (1, u'a') 1 found! Index: 18 (3, u'a') 1 e:\Work\Dev\StackOverflow\q049799109> e:\Work\Dev\StackOverflow\q049799109>"C:\Install\x64\HPE\OPSWpython\2.7.10__00\python.exe" code.py Python 2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)] on win32 Attempting Synchronous mode using a buffer 65536 bytes long... Index: 0 (2, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 deleted! Index: 1 (2, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 deleted! Index: 2 (2, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 deleted! Index: 3 (2, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 deleted! Index: 4 (2, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 deleted! Index: 5 (2, u'01234567890123456789012345678901234567890123456789.txt') 54 deleted! Index: 6 (2, u'0123456789012345678901234567890123456789.txt') 44 deleted! Index: 7 (2, u'012345678901234567890123456789.txt') 34 deleted! (2, u'01234567890123456789.txt') 24 deleted! (2, u'0123456789.txt') 14 deleted! Index: 8 (1, u'0123456789.txt') 14 found! Index: 9 (3, u'0123456789.txt') 14 Index: 10 (1, u'01234567890123456789.txt') 24 found! Index: 11 (3, u'01234567890123456789.txt') 24 Index: 12 (1, u'012345678901234567890123456789.txt') 34 found! Index: 13 (3, u'012345678901234567890123456789.txt') 34 Index: 14 (1, u'0123456789012345678901234567890123456789.txt') 44 found! Index: 15 (3, u'0123456789012345678901234567890123456789.txt') 44 Index: 16 (1, u'01234567890123456789012345678901234567890123456789.txt') 54 found! (3, u'01234567890123456789012345678901234567890123456789.txt') 54 Index: 17 (1, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 found! (3, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 (1, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 found! Index: 18 (3, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 (1, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 found! (3, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 (1, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 found! (3, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 (1, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 found! (3, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 Index: 20 (2, u'a') 1 deleted! e:\Work\Dev\StackOverflow\q049799109> e:\Work\Dev\StackOverflow\q049799109>"C:\Install\x64\HPE\OPSWpython\2.7.10__00\python.exe" code.py Python 2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)] on win32 Attempting Asynchronous mode using a buffer 512 bytes long... Index: 0 Index: 1 (2, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 deleted! Index: 2 (2, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 deleted! Index: 3 (2, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 deleted! Index: 4 (2, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 deleted! Index: 5 (2, u'01234567890123456789012345678901234567890123456789.txt') 54 deleted! Index: 6 (2, u'0123456789012345678901234567890123456789.txt') 44 deleted! Index: 7 (2, u'012345678901234567890123456789.txt') 34 deleted! Index: 8 (2, u'01234567890123456789.txt') 24 deleted! Index: 9 (2, u'0123456789.txt') 14 deleted! Index: 10 Index: 11 Index: 12 (1, u'0123456789.txt') 14 found! Index: 13 (1, u'01234567890123456789.txt') 24 found! Index: 14 (1, u'012345678901234567890123456789.txt') 34 found! Index: 15 (3, u'012345678901234567890123456789.txt') 34 Index: 16 (1, u'0123456789012345678901234567890123456789.txt') 44 found! (3, u'0123456789012345678901234567890123456789.txt') 44 Index: 17 Index: 18 (1, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 found! Index: 19 Index: 20 (1, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 found! Index: 21 Index: 22 Index: 23 Index: 24 e:\Work\Dev\StackOverflow\q049799109> e:\Work\Dev\StackOverflow\q049799109>"C:\Install\x64\HPE\OPSWpython\2.7.10__00\python.exe" code.py Python 2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)] on win32 Attempting Asynchronous mode using a buffer 65536 bytes long... Index: 0 Index: 1 (2, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 deleted! Index: 2 (2, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 deleted! Index: 3 (2, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 deleted! Index: 4 (2, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 deleted! Index: 5 (2, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 deleted! Index: 6 (2, u'01234567890123456789012345678901234567890123456789.txt') 54 deleted! Index: 7 (2, u'0123456789012345678901234567890123456789.txt') 44 deleted! Index: 8 (2, u'012345678901234567890123456789.txt') 34 deleted! (2, u'01234567890123456789.txt') 24 deleted! Index: 9 (2, u'0123456789.txt') 14 deleted! Index: 10 Index: 11 Index: 12 (1, u'0123456789.txt') 14 found! Index: 13 (1, u'01234567890123456789.txt') 24 found! Index: 14 (1, u'012345678901234567890123456789.txt') 34 found! Index: 15 (3, u'012345678901234567890123456789.txt') 34 (1, u'0123456789012345678901234567890123456789.txt') 44 found! (3, u'0123456789012345678901234567890123456789.txt') 44 Index: 16 (1, u'01234567890123456789012345678901234567890123456789.txt') 54 found! (3, u'01234567890123456789012345678901234567890123456789.txt') 54 (1, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 found! (3, u'012345678901234567890123456789012345678901234567890123456789.txt') 64 (1, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 found! Index: 17 (3, u'0123456789012345678901234567890123456789012345678901234567890123456789.txt') 74 (1, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 found! (3, u'01234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 84 (1, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 found! (3, u'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 94 (1, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 found! (3, u'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.txt') 104 Index: 18 Index: 19
备注:
底线是没有避免丢失事件的方法。采取的每项措施都可以通过增加生成事件的数量来“打败”。
减少损失:
win32con.FILE_NOTIFY_CHANGE_FILE_NAME
在脚本开头使用from win32con import FILE_NOTIFY_CHANGE_FILE_NAME
,并且只在循环中使用FILE_NOTIFY_CHANGE_FILE_NAME(以避免模块中的变量查找)
不要使用函数(因为调用/ ret类似指令) - 不确定
尝试使用win32file.GetQueuedCompletionStatus
方法获取结果(仅限异步)
事情往往会变得更好(当然也有例外),尝试切换到更新的Python版本。也许它会跑得更快
使用C - 这可能是不可取的,但它可能有一些好处:
pywin32执行的Python和C之间不会有来回转换 - 但我没有使用分析器来检查它们花费了多少时间
lpCompletionRoutine(pywin32不提供)也可用,也许它更快
作为替代方案,可以使用ctypes调用C,但这需要一些工作,我觉得它不值得