Show HN: Watchpoints, an easy to use watchpoints equivalent library for Python
github.com
github.com
from watchpoints import watch
a = []
watch(a)
a.append(1) # Trigger
a = {} # Trigger
HOW?! I demand an explanation.How does the second trigger fire? Deterministically, without relying on GC tricks? It’s watching a variable name, somehow.
Does it hook into globals()? But how would it know it needs to?
It then uses sys.settrace (which is intended as an interface for debuggers) to step through the code and check whether the variable has been changed. Documentation on sys.settrace: https://docs.python.org/3/library/sys.html#sys.settrace
Python exposes most of its guts as part of the standard library, making clever hacks like this possible.
Not that you’d want to, but it’s a fun thought experiment.
And it's a little more than inspect and frames. Note that it is much easier to do watch("a") than watch(a), but it's slightly less intuitive. So I also did some AST hack to make watch(a) possible :)
Are you on Twitter or anything? I'd like to follow your work. (Put some info in your HN profile!)
I noticed that watchpoints doesn't work in the REPL, and since I live in the REPL, it limits my usage somewhat. But after digging into the code, I'm not quite sure if it even makes sense in the context of <stdin>...
I was also -- as the other commenter said, excuse the french -- fucking amazed that this works great:
from watchpoints import watch
a = []
watch(a)
a.append(1) # Trigger
a = {} # Trigger
def qq():
global a
a = 99 # Trigger
qq()
Did not expect that.watchpoints does not work in the REPL. REPL is a more complicated environment. I don't think pdb will work in REPL either.
watchpoints works very intuitively. It has some dirty magic that made it work in some way that you need but not expect.
I've been working on a tool for automatically suggesting performance fixes to python apps based on static analysis and dynamic profiling. This is a nice method adding additional dynamic information that you need for certain optimizations. (E.g. if you want to suggest replacing a list with a set then you need to know how that list is used which sometimes can be hard with static analysis.)
Also I already implemented the pdb hook so this could work like breakpoint() in built-in library.