ここまでで監視用 watch フォルダに新たに設置したファイルが自動的に処理される仕組みを作ってきました.ここではどのようなタイミングでそれらの処理が進んでいくのかが分かるように,処理を行ったタイムスタンプも出力するように微調整します.
具体的には,次のとおり datetime ラブラリをインポートした上で,全体的に print に時間を表示するコードを追加します.
watch.py
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import shutil # ファイルのコピー,移動などを行う標準ライブラリ
import time
import datetime
BASE_DIR = Path(__file__).parent
WATCH_DIR = BASE_DIR / "watch"
QUEUE_DIR = BASE_DIR / "queue"
# ディレクトリを作っておく
WATCH_DIR.mkdir(parents=True, exist_ok=True)
QUEUE_DIR.mkdir(parents=True, exist_ok=True)
def wait_until_complete(path):
"""
watch ディレクトリへのコピー,ファイルサイズの変化がない -> コピー(ダウンロード)が終わったと判断
待っている間にファイル名が変更されたら強制終了
"""
while True:
try:
size1 = path.stat().st_size
time.sleep(5)
size2 = path.stat().st_size
time.sleep(5)
size3 = path.stat().st_size
if size1 == size2 == size3:
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] ファイルの受取りが完了しました")
return True
except FileNotFoundError:
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] ファイルが見つかりません: {path}") # 途中でファイル名を変更したり,削除した場合
return False
class MyHandler(FileSystemEventHandler):
"""
watchdog が用意している FileSystemEventHandler クラスの継承
「ファイル監視イベントが発生したときに何をするか」を定義する
"""
def on_created(self, event):
if event.is_directory: # ディレクトリは無視
return
src = Path(event.src_path)
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 新しいファイルを検出: {src}")
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 新しいファイルの名前: {src.name}")
if not wait_until_complete(src):
return
dst = QUEUE_DIR / src.name # 移動先の指定
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] ファイルの移動開始: {dst}")
shutil.move(src, dst) # ファイルの移動
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] ファイルの移動完了: {dst}")
observer = Observer() # 「監視員を作成する」処理
# 監視条件設定
observer.schedule(
MyHandler(),
path=WATCH_DIR,
recursive=False # とりあえず直下だけを監視
)
observer.start() # 監視を始める → 別スレッド(observerスレッド)が生成される
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 停止します")
observer.stop()
observer.join() # observerスレッドが終わるまで待つ
worker.py
from pathlib import Path
import shutil
import time
import datetime
BASE_DIR = Path(__file__).parent
QUEUE_DIR = BASE_DIR / "queue"
WORKING_DIR = BASE_DIR / "working"
DONE_DIR = BASE_DIR / "done"
# ディレクトリを作っておく
QUEUE_DIR.mkdir(parents=True, exist_ok=True)
WORKING_DIR.mkdir(parents=True, exist_ok=True)
DONE_DIR.mkdir(parents=True, exist_ok=True)
try:
while True:
for src in QUEUE_DIR.glob("*.m*"): # 監視するファイルの拡張子
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 処理開始: {src.name}")
working_file = WORKING_DIR / src.name
shutil.move(src, working_file)
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 作業開始: {working_file}")
# with open(working_file, "r", encoding="utf-8") as f:
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 処理中...")
time.sleep(25)
# print(f.read())
dst = DONE_DIR / src.name
shutil.move(working_file, dst)
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 完了: {dst}")
time.sleep(1)
except KeyboardInterrupt:
print(f"[{datetime.datetime.now().strftime('%H:%M:%S.%f')}] 停止します")
ターミナルを2個起動し,それぞれで watch.py と worker.py を実行します.
(py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog> python watch.py ⏎
(py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog> python worker.py ⏎
監視用 watch フォルダに4つのマークダウンファイルをまとめて設置した後の作業状況を確認します.まず,1個目のファイル (sample1.md) がその設置から10秒後に待ち行列用 queue フォルダに移動しました.その後もおよそ10秒間隔で順番に待ち行列フォルダに移動し,約40秒で全ての処理が終了しました.
(py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog> python watch.py [16:39:19.456446] 新しいファイルを検出: C:\Users\rinsaka\Documents\python\watchdog\watch\sample1.md [16:39:19.456802] 新しいファイルの名前: sample1.md [16:39:29.458173] ファイルの受取りが完了しました [16:39:29.458471] ファイルの移動開始: C:\Users\rinsaka\Documents\python\watchdog\queue\sample1.md [16:39:29.459531] ファイルの移動完了: C:\Users\rinsaka\Documents\python\watchdog\queue\sample1.md [16:39:29.459735] 新しいファイルを検出: C:\Users\rinsaka\Documents\python\watchdog\watch\sample2.md [16:39:29.459881] 新しいファイルの名前: sample2.md [16:39:39.461279] ファイルの受取りが完了しました [16:39:39.461669] ファイルの移動開始: C:\Users\rinsaka\Documents\python\watchdog\queue\sample2.md [16:39:39.462567] ファイルの移動完了: C:\Users\rinsaka\Documents\python\watchdog\queue\sample2.md [16:39:39.462640] 新しいファイルを検出: C:\Users\rinsaka\Documents\python\watchdog\watch\sample3.md [16:39:39.462726] 新しいファイルの名前: sample3.md [16:39:49.463796] ファイルの受取りが完了しました [16:39:49.463954] ファイルの移動開始: C:\Users\rinsaka\Documents\python\watchdog\queue\sample3.md [16:39:49.464343] ファイルの移動完了: C:\Users\rinsaka\Documents\python\watchdog\queue\sample3.md [16:39:49.464481] 新しいファイルを検出: C:\Users\rinsaka\Documents\python\watchdog\watch\sample4.md [16:39:49.464569] 新しいファイルの名前: sample4.md [16:39:59.465976] ファイルの受取りが完了しました [16:39:59.466153] ファイルの移動開始: C:\Users\rinsaka\Documents\python\watchdog\queue\sample4.md [16:39:59.466968] ファイルの移動完了: C:\Users\rinsaka\Documents\python\watchdog\queue\sample4.md Ctrl + C [16:41:20.109003] 停止します (py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog>
一方でワーカープログラムの処理状況を確認します.最初のファイルが監視フォルダから移動した [16:39:29.459531] からおよそ0.5秒後の [16:39:29.963498] に処理が始まりました.この待ち時間は worker.py の30行目で1秒間のスリープを入れていることから,少なくとも1秒以内に処理が始まることになります.全てのファイルの処理が終わるまでにおよそ100秒を要していることも確認できます.これは worker.py の25行目で25秒間のスリープを入れていることが原因です.
(py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog> python worker.py [16:39:29.963498] 処理開始: sample1.md [16:39:29.964485] 作業開始: C:\Users\rinsaka\Documents\python\watchdog\working\sample1.md [16:39:29.964619] 処理中... [16:39:54.965770] 完了: C:\Users\rinsaka\Documents\python\watchdog\done\sample1.md [16:39:55.966500] 処理開始: sample2.md [16:39:55.967091] 作業開始: C:\Users\rinsaka\Documents\python\watchdog\working\sample2.md [16:39:55.967278] 処理中... [16:40:20.968543] 完了: C:\Users\rinsaka\Documents\python\watchdog\done\sample2.md [16:40:20.968738] 処理開始: sample3.md [16:40:20.969236] 作業開始: C:\Users\rinsaka\Documents\python\watchdog\working\sample3.md [16:40:20.969326] 処理中... [16:40:45.970508] 完了: C:\Users\rinsaka\Documents\python\watchdog\done\sample3.md [16:40:46.971412] 処理開始: sample4.md [16:40:46.971893] 作業開始: C:\Users\rinsaka\Documents\python\watchdog\working\sample4.md [16:40:46.971951] 処理中... [16:41:11.973023] 完了: C:\Users\rinsaka\Documents\python\watchdog\done\sample4.md Ctrl + C [16:41:21.276348] 停止します (py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog>
全ての処理が終了した後には完了用の done フォルダに全てのファイルが移動しています.
(py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog> gci done ⏎
ディレクトリ:C:\Users\rinsaka\Documents\python\watchdog\done
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2026/10/25 18:18 56 sample1.md
-a--- 2026/10/25 18:18 115 sample2.md
-a--- 2026/10/25 18:19 47 sample3.md
-a--- 2026/10/25 18:19 59 sample4.md
(py313watchdog) PS C:\Users\rinsaka\Documents\python\watchdog>