python
39 lines · 8 steps
Polling a directory for file changes in Python
A simple poller that detects created, deleted, and modified files by diffing snapshots of modification times.
Explained by
highlit
1import os
2import time
3from pathlib import Path
4
5
6def watch_directory(path, on_change, interval=1.0, pattern="*"):
7 directory = Path(path)
8 snapshot = _snapshot(directory, pattern)
9
10 while True:
11 time.sleep(interval)
12 current = _snapshot(directory, pattern)
13
14 created = current.keys() - snapshot.keys()
15 deleted = snapshot.keys() - current.keys()
16 modified = {
17 f for f in current.keys() & snapshot.keys()
18 if current[f] != snapshot[f]
19 }
20
21 for f in sorted(created):
22 on_change("created", f)
23 for f in sorted(deleted):
24 on_change("deleted", f)
25 for f in sorted(modified):
26 on_change("modified", f)
27
28 snapshot = current
29
30
31def _snapshot(directory, pattern):
32 snapshot = {}
33 for entry in directory.glob(pattern):
34 if entry.is_file():
35 try:
36 snapshot[str(entry)] = entry.stat().st_mtime_ns
37 except OSError:
38 continue
39 return snapshot
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Comparing two snapshots with set operations cleanly separates created, deleted, and modified into three cases.
- 2Storing modification times lets you detect edits, not just additions and removals.
- 3Polling trades responsiveness and CPU cost against simplicity — no OS-specific file-watch APIs needed.
Related explainers
ruby
class Order class InvalidTransition < StandardError; end TRANSITIONS = {
A state machine for order transitions in Ruby
state-machine
data-driven
error-handling
Intermediate
8 steps
python
from flask import Blueprint, jsonify, request, abort v1 = Blueprint("users_v1", __name__) v2 = Blueprint("users_v2", __name__)
Versioning a Flask API with Blueprints
api versioning
blueprints
rest
Intermediate
7 steps
python
import time import threading from enum import Enum from functools import wraps
Building a circuit breaker in Python
circuit-breaker
resilience
decorators
Advanced
7 steps
python
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector from django.core.cache import cache from django.db.models import F from django.http import JsonResponse
Ranked full-text search in Django
full-text-search
debouncing
caching
Advanced
9 steps
python
import os from datetime import timedelta
Class-based config in a Flask app factory
configuration
app-factory
inheritance
Intermediate
7 steps
python
import time from flask import Flask, g, request
Timing requests with Flask hooks
middleware
request-lifecycle
instrumentation
Intermediate
5 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/polling-a-directory-for-file-changes-in-python-explained-python-3b36/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.