Pythonにフォルダ更新を通知させる

# 目次
・背景
・目的
・内容
・所感

# 背景・課題
月次業務で、毎月月初に他部署の方に作成して頂いたファイルを使って、私が集計を行うというものがある。
これまでは、私が直接フォルダを見に行って最新のファイルがアップされているかどうかを目視確認していたが、月によって若干更新タイミングが違うため、ファイルにアクセスしにいく作業が非効率＆無駄である。

# 目的
面倒なことはPythonにやらせたい:muscle_tone1:
Pythonに更新タイミングで通知をさせることで、人間の私がフォルダにアクセスする回数を1回のみにして、無駄工数を減らしたい:muscle_tone1:

# 内容
######   ■ コンセプト
Pythonで特定のフォルダにファイルが追加された際に通知を受け取るためのプログラムを作成するには、plyer、win10toast、watchdog等を使用するのが一般的なようである。

| ライブラリ   | 説明                                                                                                      | OS                                      |
|--------------|-----------------------------------------------------------------------------------------------------------|-----------------------------------------|
| plyer        | Pythonでクロスプラットフォームの機能を利用するためのライブラリ。プラットフォーム固有の機能（例えば、通知、バイブレーション、ファイル選択ダイアログなど）を、プラットフォームに依存することなく利用可能。 | Windows、macOS、Linux、iOS、Androidなど |
| win10toast   | Windows 10のデスクトップ通知を簡単に表示するためのPythonライブラリ。トースト通知（スクリーンの右下に一時的に表示される小さなポップアップウィンドウ）を表示することができる。 | 主にWindows 10                             |
| Watchdog     | ファイルシステムの変更を監視するためのPythonライブラリ。特定のディレクトリやファイルに対する変更をリアルタイムで検出し、それに応じたアクションを実行することができる。イベント駆動型のAPIを提供し、ファイルシステムのイベントを監視するためのハンドラを簡単に作成できる。 | ？    

今回はplyerとwatchdogを使用して、フォルダを監視しファイルが追加されたときにコンソール通知を出力させるようにする。

オブジェクト指向ワナビーかつplyerは初めてなので、まずは"Hello World"させてみた。
```python
from plyer import notification

# 通知を表示する関数
def show_notification(title, message):
    notification.notify(
        title=title,
        message=message,
        app_name='Notification App',
        timeout=10  # 通知が表示される時間
    )

# メイン関数
if __name__ == "__main__":
    show_notification("Hello", "Hello World")
```


###   ■ 実際のコード

######   ■ 初期設定
```python
pip install watchdog
pip install plyer
```

```python
import os
from plyer import notification
import datetime as dt
import time

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from plyer import notification  # plyerからnotificationをインポート
```


######   ■ フォルダ監視パート

やらせていること：

・特定フォルダの監視
・監視に引っかかった際のイベント発砲


```python
class Watcher:
    DIRECTORY_TO_WATCH = r"\\xxxx\xxxx\xxxx\xxxx"
    #パスを`DIRECTORY_TO_WATCH`というクラス変数に保持
    
    def __init__(self):
        self.observer = Observer() #`Observer`オブジェクトを作成し、`self.observer`に代入

    def run(self):
        event_handler = Handler()
        self.observer.schedule(event_handler, self.DIRECTORY_TO_WATCH, recursive=True)
        #`recursive=True`でサブディレクトリも監視させてみる
        
        self.observer.start()
        try:
            while True:
                time.sleep(30) #無限ループで監視継続
        except:
            self.observer.stop()
            print("Observer Stopped")
            #例外が発生した場合(私が手動で停止した場合etc.)に監視停止メッセージ表示

        self.observer.join()
         #最後に`self.observer.join()`を呼び出して、監視スレッド終了待ち

```


######   ■ 通知パート
やらせていること：

・イベント発砲を受け取って通知できる形に変換
・上記形式をポップアップ表示


```python
class Handler(FileSystemEventHandler):

    @staticmethod
    def on_any_event(event):
        if event.is_directory:
            return None

        elif event.event_type == 'created':
            # ファイルがUPされたときにデスクトップ通知を表示
            notification.notify(
                title='最新fileリリース',
                message=f'最新fileが来たから集計して: {event.src_path}',
                app_name='folder監視アプリ',
                timeout=120  # 通知が表示される時間（秒）
            )
            print(f"Received created event - {event.src_path}.")

if __name__ == '__main__':
    w = Watcher()
    w.run()
```

テスト段階では、「Vscode上にはファイル更新の通知は出るし、エラーも出ていないのに、PCにはポップアップが出ない！」となり、win10toastも試したりしていたが、結局コードに罪はなく、PC本体の設定ミスだったりした。 

ギリギリ実務の本番のタイミングに間に合い、意図した通りに11個通知が来てくれた。とてもうれしい。:relaxed::tulip:

# 所感
plyerライブラリは色々な使い方がありそうなので、他の使い方も実装してみたい。

動作確認はできているので、記載したコードは任意のパスやメッセージに書き換えて転用していただいて構いません。
最後まで読んでいただき、ありがとうございました。