11

Windows 2012 サーバーで Python ウォッチドッグ モジュールを使用して、共有ドライブに表示される新しいファイルを監視しています。ウォッチドッグが新しいファイルを認識すると、データベースの復元プロセスが開始されます。

ただし、ウォッチドッグは、ファイルが作成された瞬間にファイルの復元を試み、ファイルが共有ドライブへのコピーを完了するまで待機しないようです。そのため、イベントを on_modified に変更しましたが、2 つの on_modified イベントがあり、1 つはファイルが最初にコピーされたとき、もう 1 つはコピーが完了したときです。

2 つの on_modified イベントを処理して、共有ドライブへのファイルのコピーが完了したときにのみ発生させるにはどうすればよいですか?

複数のファイルが共有ドライブに同時にコピーされるとどうなりますか?

これが私のコードです

import time
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class NewFile(FileSystemEventHandler):
    def process(self, event):
        if event.is_directory:
            return

    if event.event_type == 'modified':            
        if getext(event.src_path) == 'gz':
            load_pgdump(event.src_path)

    def on_modified(self, event):
        self.process(event)

def getext(filename):
    "Get the file extension"
    file_ext = filename.split(".",1)[1]
    return file_ext

def load_pgdump(src_path):    
    restore = 'pg_restore command ' + src_path
    subprocess.call(restore, shell=True)

def main():
    event_handler = NewFile()
    observer = Observer()
    observer.schedule(event_handler, path='Y:\\', recursive=True)
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

if __name__ == '__main__':
    main()
4

9 に答える 9

10

on_modified イベントでは、ファイル サイズを監視して、ファイルのコピーが完了するまで待ちます。

よりシンプルなループの提供:

historicalSize = -1
while (historicalSize != os.path.getsize(filename)):
  historicalSize = os.path.getsize(filename)
  time.sleep(1)
print "file copy has now finished"
于 2016-12-12T16:29:33.743 に答える
3

次のコードを使用して、ファイルがコピーされるまで待機しています (Windows のみ)。

from ctypes import windll
import time

def is_file_copy_finished(file_path):
    finished = False

    GENERIC_WRITE         = 1 << 30
    FILE_SHARE_READ       = 0x00000001
    OPEN_EXISTING         = 3
    FILE_ATTRIBUTE_NORMAL = 0x80

    if isinstance(file_path, str):
        file_path_unicode = file_path.decode('utf-8')
    else:
        file_path_unicode = file_path

    h_file = windll.Kernel32.CreateFileW(file_path_unicode, GENERIC_WRITE, FILE_SHARE_READ, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None)

    if h_file != -1:
        windll.Kernel32.CloseHandle(h_file)
        finished = True

    print 'is_file_copy_finished: ' + str(finished)
    return finished

def wait_for_file_copy_finish(file_path):
    while not is_file_copy_finished(file_path):
        time.sleep(0.2)

wait_for_file_copy_finish(r'C:\testfile.txt')

アイデアは、共有読み取りモードで書き込み用にファイルを開こうとすることです。他の誰かが書き込んでいると失敗します。

楽しみ ;)

于 2017-10-09T10:49:05.467 に答える
1

Linux ではcloseイベントも発生します。解決策よりも、ファイルが閉じられるまでファイルの処理を待つことです。私のアプローチは、on_closed処理を追加することです。

class Handler(FileSystemEventHandler):
    def __init__(self):
        self.files_to_process = set()

    def dispatch(self, event):
        _method_map = {
            'created': self.on_created,
            'closed': self.on_closed
        }

    def on_created(self, event):
        self.files_to_process.add(event.src_path)

    def on_closed(self, event):
        self.files_to_process.remove(event.src_path)
        actual_processing(event.src_path)
于 2021-09-01T12:03:17.427 に答える