4

ReadDirectoryChangesW を使用してサブツリーのファイル変更を監視しようとしましたが、一貫性のない結果が得られることがわかりました。以下は、問題を説明する自己完結型のテスト ケースです。これを実行すると、次のように生成されることがあります。

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
4

1 に答える 1

0

ここでの問題は、渡されるタイムアウトWaitForSingleObjectが非常に短いため、イベントに関する通知を受け取る前に関数がタイムアウトする傾向があることです。コードはその条件をチェックしないため、出力が表示されません (rc > 0もテストしてみてください)。

INFINITEの値(つまり 0xFFFFFFFF) を に渡すことで、これを修正できますWaitForObject

于 2016-11-01T14:43:43.770 に答える