51246


watchdogでフォルダを監視して変更があった場合printするものなんですが  
なぜかon_modifiedの中身が二回表示されます。  
以下がソースと結果です。

[code]

    # -*- coding: utf-8 -*-
    
    from watchdog.events import FileSystemEventHandler
    from watchdog.observers import Observer
    
    import os
    import time
    
    target_dir = r"対象フォルダのパス"
    
    class ChangeHandler(FileSystemEventHandler):
        def on_modified(self, event):
            filepath = event.src_path
            filename = os.path.basename(filepath)
            print('%sを変更しました' % filename)
    
    if __name__ in '__main__':
        while 1:
            event_handler = ChangeHandler()
            observer = Observer()
            observer.schedule(event_handler, target_dir, recursive=True)
            observer.start()
            try:
                while True:
                    time.sleep(0.1)
            except KeyboardInterrupt:
                observer.stop()
            observer.join()
    
[/code]

このファイルを実行して、対象フォルダにある例えばtest.txtを編集して保存を1度すると実行中の窓に

[code]

    test.txtを変更しました
    test.txtを変更しました
    
[/code]

と、二度printされてしまいます。  
どうすればちゃんと編集された回数分の1回だけ出るようになるのでしょうか？  
ちなみに下記のようなon_createdは期待通りの動きで

[code]

    class ChangeHandler(FileSystemEventHandler):
        def on_created(self, event):
            filepath = event.src_path
            filename = os.path.basename(filepath)
            print('%sができました' % filename)
    
        def on_modified(self, event):
            filepath = event.src_path
            filename = os.path.basename(filepath)
            print('%sを変更しました' % filename)
    
[/code]

これで新しいテキストファイルを作ると1度だけ～ができました、と出ます。  
でもこの状態で例えばtest.txtをCtrl+D&Dで同じフォルダ内にコピーすると

[code]

    test - コピー.txtができました
    test - コピー.txtを変更しました
    test - コピー.txtを変更しました
    
[/code]

やはりmodifiedのほうは二回分こう出力されます。  
ご指導宜しくお願い致します。

追記:以下環境です。  
OS Windows7 64bit  
Python 3.7.1  
Watchdog 0.9.0  
以上です、宜しくお願いします。


CC BY-SA 4.0
2018-12-16T02:59:44.473
51242
2022-06-15T02:43:08.180
2018-12-16T04:30:55.403
19110
31469
question
python
pythonでwatchdogのイベントが二回発火してる原因が分からない


# 原因？

実装に問題はなさそうなので、編集して保存する際のエディタの挙動なのでは、という気がします。

# 対策

ファイルの変更が通知されるタイミングでハッシュを確認し、変更があれば通知する、という実装に変えてみてはいかがでしょうか。以下サンプルです

[code]

    import hashlib
    hashes = {}
    
    def on_modified(self, event):
        filepath = event.src_path
        filename = os.path.basename(filepath)
        with open(filepath, 'rb') as f:
            checksum = hashlib.md5(f.read()).hexdigest()
        if filename not in hashes or (hashes[filename] != checksum):
            hashes[filename] = checksum
            print('%sを変更しました' % filename)
        else:
            # ハッシュが既存のものと変更していない
            pass
    
[/code]


CC BY-SA 4.0
2018-12-16T04:38:28.360
51246
2018-12-16T04:38:28.360
29826
51242
answer


PollingObserverを使用することで解決できました。

[code]

    from watchdog.observers.polling import PollingObserver
    
[/code]

[code]

    observer = PollingObserver()
    
[/code]


CC BY-SA 4.0
2022-06-15T02:43:08.180
89391
2022-06-15T02:43:08.180
53073
51242
answer