Python ReadDirectoryChangesW似乎缺少事件
我一直试图让ReadDirectoryChangesW监视子树中的文件更改,但我发现结果不一致。下面是一个自包含的测试用例,它说明了这个问题。当我运行此程序时,它有时会生成:Python ReadDirectoryChangesW似乎缺少事件,python,windows,readdirectorychangesw,Python,Windows,Readdirectorychangesw,我一直试图让ReadDirectoryChangesW监视子树中的文件更改,但我发现结果不一致。下面是一个自包含的测试用例,它说明了这个问题。当我运行此程序时,它有时会生成: A : Created C : Updated A : Deleted 另一次可能会产生: A : Created B : Updated C : Updated A : Deleted 我创建了一个巨大的缓冲区,被更改的文件数量非常少(3个文件) 守则: import os, sys, time, threading
A : Created
C : Updated
A : Deleted
另一次可能会产生:
A : Created
B : Updated
C : Updated
A : Deleted
我创建了一个巨大的缓冲区,被更改的文件数量非常少(3个文件)
守则:
import os, sys, time, threading
import win32file, win32event, win32con, pywintypes
class ChangeFiles ( threading.Thread ) :
def run( self ) :
files = [ 'A', 'B', 'C' ]
time.sleep( 1 )
for path in files : f = open( path, 'w' ); f.write( 'mooo' ); f.close()
time.sleep( 0.5 )
for path in files : os.remove( path )
ChangeFiles().start()
FILE_LIST_DIRECTORY = 0x0001
handle = win32file.CreateFile (
'.',
FILE_LIST_DIRECTORY,
win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
None,
win32con.OPEN_EXISTING,
win32con.FILE_FLAG_BACKUP_SEMANTICS | win32file.FILE_FLAG_OVERLAPPED,
None
)
buffer = win32file.AllocateReadBuffer( 1024 * 64 )
overlapped = pywintypes.OVERLAPPED()
overlapped.hEvent = win32event.CreateEvent( None, 0, 0, None )
readFlags = 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
ACTIONS = { 1 : "Created", 2 : "Deleted", 3 : "Updated" }
while 1 :
win32file.ReadDirectoryChangesW( handle, buffer, False, readFlags, overlapped )
rc = win32event.WaitForSingleObject( overlapped.hEvent, 200 )
if rc == win32event.WAIT_OBJECT_0 :
nbytes = win32file.GetOverlappedResult( handle, overlapped, True )
if nbytes > 0 :
for action, file in win32file.FILE_NOTIFY_INFORMATION( buffer, nbytes ) :
print '%s : %s' % ( file, ACTIONS.get ( action, "Unknown" ) )
else :
print 'no bytes'
break
elif rc < 0 :
print 'Error: %d' % win32api.GetLastError()
break
导入操作系统、系统、时间、线程
导入win32file、win32event、win32con、pywintypes
类ChangeFiles(threading.Thread):
def运行(自):
文件=['A','B','C']
时间。睡眠(1)
对于文件中的路径:f=open(路径“w”);f、 写('mooo');f、 关闭()
睡眠时间(0.5)
对于文件中的路径:os.remove(路径)
ChangeFiles().start()
文件列表目录=0x0001
handle=win32file.CreateFile(
'.',
文件列表目录,
win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE,
没有一个
win32con.OPEN_存在,
win32con.FILE_FLAG_BACKUP_语义| win32file.FILE_FLAG_重叠,
没有一个
)
buffer=win32file.allocateradbuffer(1024*64)
overlapped=pywintypes.overlapped()
overlapped.hEvent=win32event.CreateEvent(无,0,0,无)
readFlags=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\u通知\u更改\u安全性
操作={1:“已创建”,2:“已删除”,3:“已更新”}
而1:
win32file.ReadDirectoryChangesW(句柄、缓冲区、False、readFlags、重叠)
rc=win32event.WaitForSingleObject(overlapped.hEvent,200)
如果rc==win32event.WAIT\u对象\u 0:
nbytes=win32file.GetOverlappedResult(句柄,重叠,True)
如果N字节>0:
要执行操作,请在win32file.file\u NOTIFY\u信息(缓冲区,N字节)中输入文件:
打印“%s:%s%”(文件,ACTIONS.get(操作,“未知”))
其他:
打印“无字节”
打破
elif rc<0:
打印错误:%d'%win32api.GetLastError()
打破
这里的问题是,您传递给WaitForSingleObject
的超时非常低,因此函数往往会在收到事件通知之前超时。您的代码没有检查该条件,因此您看不到任何输出(也可以尝试测试rc>0
)
您可以通过将
INFINITE
(即0xffffff)的值传递给WaitForObject
来解决此问题。我开始猜测,如果一棵树倒在森林中,周围没有人听到它,它还会发出声音吗?在这种情况下,如果没有对ReadDirectoryChangesW的未决调用,并且文件系统发生了更改,您以后会了解该更改吗?也许不是。我一直在使用一个名为watchdog的python库,它似乎对我有用,但我仍然想知道为什么上面的代码示例遗漏了事件。根据,在调用此函数之间发生的目录更改被添加到缓冲区,然后在下次调用时返回。所以事件应该被缓冲,直到下一次调用。我从未使用过python,但在本机代码中使用该API时没有遇到任何问题。