Skip to content

Instantly share code, notes, and snippets.

@drscotthawley
Last active April 10, 2026 21:00
Show Gist options
  • Select an option

  • Save drscotthawley/44bae7d72c693fa725692bf18126d9e5 to your computer and use it in GitHub Desktop.

Select an option

Save drscotthawley/44bae7d72c693fa725692bf18126d9e5 to your computer and use it in GitHub Desktop.
do_every: wallclock-based interval switch
# Instead of having to figure out how many steps or how many epochs I want to wait,
# (e.g. `if epochs % viz_every == 0:` or `if steps % ckpt_every == 0`)
# sometimes I'd rather have something wall-clock-time-based and easy to call.
# Hence this.
# Sample usage: `if do_every('15min'):`, or with optional id: `if do_every('1h', 'viz'):` etc.
import time
import inspect
import re
_timers = {}
def _parse_interval(s):
"""Parse a human-readable interval string or number into seconds."""
if isinstance(s, (int, float)):
return float(s)
s = str(s).strip().lower()
units = {'s': 1, 'sec': 1, 'second': 1, 'seconds': 1,
'm': 60, 'min': 60, 'minute': 60, 'minutes': 60,
'h': 3600, 'hr': 3600, 'hour': 3600, 'hours': 3600}
m = re.fullmatch(r'(\d+(?:\.\d+)?)\s*([a-z]+)', s)
if m:
val, unit = float(m.group(1)), m.group(2)
if unit in units:
return val * units[unit]
raise ValueError(f"Can't parse interval: {s!r}")
def do_every(interval, id=None, first_true=True):
"""Return True if at least `interval` time has passed since the last True at this call site.
Sample usage: do_every('15min'), do_every('1h', 'viz') etc.
If `id` is None, the call site is identified by filename and line number; otherwise, it's identified by filename and `id`.
This allows you to have multiple independent timers in the same file.
By default it will be true the first time it's called. Set first_true=False to change that.
"""
frame = inspect.stack()[1]
key = f"{frame.filename}:{id}" if id is not None else f"{frame.filename}:{frame.lineno}"
seconds = _parse_interval(interval)
now = time.time()
is_first = key not in _timers
if now - _timers.get(key, 0) >= seconds:
_timers[key] = now
return first_true if is_first else True
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment