Show HN: Change Python code while it's running using a reloading loop
github.com
github.com
if type(x) is Foo:
and mysteriously failed for some data around the reload. turns out that Foo objects from before the reload were using a different class object than Foo objects after the reload (which makes sense in hindsight, as Foo was redefined). fun times debugging that!I didn't go into as much detail as I would have liked about hot reloaders, but the tl;dr is that if you have a _single_ reference to something, then hot reloading it is somewhat simple. The problem comes when you want to hot reload a single module inside a large program.
Hot reloading a loop like this is super cool, but it only works if you're just changing constants and not defining anything. The moment you want to change the definitions of an object in the loop and hot reload it then you're in a lot of pain.
Here's the source code for IPythons autoreload magic command: https://github.com/ipython/ipython/blob/cd54f15544eee69449cc.... Take note of the Caveats section.
isinstance(x, Foo)(aside: i know that `isinstance` is the official way, but i just don't like the way it reads – "x is an instance of y" is an infix construct and looks weird in a prefix position. i don't really use inheritance so `type(x) is y` is good enough, and it reads very naturally)
If it doesn’t add much overhead this would be amusing for something like game dev, swapping out how the game works while running it.
Edit: Ah, it is https://en.wikipedia.org/wiki/Eric_S._Raymond , found after some googling
"Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp."
Ref: http://philip.greenspun.com/research/
P.S. This is not a comment on TFA. Congratulations to the author on making Python even more interactive.
https://mail.python.org/pipermail/python-dev/2003-January/03...
It refers to this, I guess. http://www.paulgraham.com/lispfaq1.html?viewfullsite=1
"If you look at these languages in order, Java, Perl, Python, you notice an interesting pattern. At least, you notice this pattern if you are a Lisp hacker. Each one is progressively more like Lisp."
This is the basic thought. Turns out PG wrote it more explicitly than ESR.
Nice that you could condense it to less than 100 lines of Python!
[1] https://pytorch.org/tutorials/beginner/saving_loading_models...
>interactive
AFAIK, as you type python code it will execute with the changes incorporated in the next loop execution. That's a heavily constraint "interactive" (forward propagating changes against an active execution). I mean, wouldn't a python shell with shell history be more interactive and hit all your goals? Sure the advantage of this is you can change code based on output feedback, but if you are too slow, you have to backtrack, and if you are too fast, you just wait anyways in both cases. And if you want to add code to earlier loop executions, you are kaput for earlier loop executions since those are set in stone against a different version of the code?
> reproducible
How can you get this, i.e. reproduce any loop changes outside of IDE/editor code undo/redo stack. It's hiding all the magic of what code outputted what with the "reloading" function.
> recordable, replayable
This moves the "history" to the IDE/editor code undo/redo stack. I think this is worse, cause, what happens when you close the IDE/editor without recording which specific console output was for which version of the code?
My main gripe is this sentence in the README:
> This lets you e.g. add logging, print statistics or save the model without restarting the training and, therefore, without losing the training progress.
If the italicised is the prime concern, and the purpose of this is to solve that, I'm just saying PyTorch already lets you save/persist training data, maybe the author didn't know about it + python shell combo?
import reloading
Traceback (most recent call last):
File "<input>", line 1, in <module>
import reloading
File "/home/lucas.mccoy/.local/lib/python2.7/site-packages/reloading/__init__.py", line 1, in <module>
from .reloading import reloading
File "/home/lucas.mccoy/.local/lib/python2.7/site-packages/reloading/reloading.py", line 87
exc = exc.replace('File "<string>"', f'File "{fpath}"')
^
SyntaxError: invalid syntax diff --git a/reloading/reloading.py b/reloading/reloading.py
index 1d28e2f..1a5f981 100644
--- a/reloading/reloading.py
+++ b/reloading/reloading.py
@@ -84,9 +84,10 @@ def reloading(seq):
exec(body)
except Exception:
exc = traceback.format_exc()
- exc = exc.replace('File "<string>"', f'File "{fpath}"')
+ exc = exc.replace('File "<string>"', 'File "{}"'.format(fpath))
sys.stderr.write(exc + '\n')
- input('Edit the file and press return to continue with the next iteration')
+ print('Edit the file and press return to continue with the next iteration')
+ sys.stdin.readline()
# copy locals back into the caller's locals
for k, v in locals().items():https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep49...
Being able to loop a specific segment of code looks like a great tool for my toolbox when writing data processing code, particularly for spatial data. I will have an input dataset and be iterating on the algorithm(s) as I watch the output (often rendered in QGIS) update dynamically but requiring me to re-run the test script.
Being able to modify code during a run, where it has a heavy startup cost, is a different beast. I also wonder if Django's runserver could incorporate something like `reloading`, for even speedier reloads?
- Always run from the back buffer
- Always scan the updated file into the front buffer
- If the front buffer is fresh AND the front buffer contains no bugs, bufferswap
$ vi ~/.functions # fix
$ . ~/.functions # load latest