Hello! I’m a new contributor, so please let me know if this is the wrong way to suggest an enhancement.
My proposal is to add a warning for when a module has been altered since it was imported in the REPL. I think this would be helpful for these reasons:
Users working on a module may occasionally forget to restart the REPL after making changes and spend unnecessary time debugging outdated behavior
New Python users may not be aware that imported modules do not self-update
Tracebacks can show stale or incorrect lines in this condition, which feels inappropriate even if due to otherwise expected behavior. I would say that if we’re in the business of making error text more helpful in other areas, such as suggesting spelling corrections, this would be a fitting issue to smooth over
Some possible matters of discussion I can already think of (in addition to whether people like this idea) include:
I would not be surprised if it was a needly process figuring out where to put these checks; it would be especially good to hear from people more familiar with the code surrounding imports and the repl than I am at present
The method for monitoring a file for changes will vary between operating systems
In-practice opinions such as whether a warning should fire as soon as a module is changed or only when the changed module is accessed
What does everyone think, is this something worth considering?
Yeah, that is a rather tricky problem. But there might be a solution. It involves firing the event as soon as the module is changed (per your third thought). What you could have - and this could, I believe, be done with an import hook - would be something like this:
You attempt to import something: import spam
Python discovers this file in your script directory (as opposed to the standard library - no need to do this for the stdlib)
An inotify hook is set up (or equivalent on other platforms - fsevents on a Mac, not sure what Windows has)
The module gets imported as normal
You edit the file and save back under the same name. This will trigger a CLOSE_WRITE event.
There’s an immediate message in the console, suggesting that you restart.
This should be doable, though it might be a bit of work. Would that cover your needs?
Yes, that sounds like it would work perfectly. Doing it immediately probably is the simplest way to implement this too, now that I think about it a little bit more.
Cool. I’d recommend making this as a personal tool initially, and then offering it to everyone. That way, you only need to worry about one OS, which cuts your work significantly - getting notified when a file is edited involves different behaviours on different OSes, so you’d have to cope with all of that if you try to make this fully general.
You could actually have this as a self-notify inside a module, come to think of it. You could start your module off with something like this:
import utils # a module of your own creation - name it after yourself if you like
utils.report_on_edit(__file__)
Then the report_on_edit function doesn’t need to be an import hook or anything - it just takes a file name and tells you whenever it changes. And, bonus - you can even have the utils module use this itself, which would be tricky with an import hook.
Since the goal is for this to be useful for beginners, that doesn’t quite make sense - ideally is part of a courses setup, which means it should be very easy to install.
Come to think, putting it that way makes me wonder if it would be helpful to just make it reload the module instead. I suppose at that point, whether or not to contribute the functionality back (/whether or not it would be accepted) would be down to whether this breaks any existing paradigms, but if it could be made to work for nested imports (and if it didn’t break anything else) it could be handy for working on things like modules imported by flask apps. It would still address the “stale lines in traceback data” issue, too. I’ll have to think about this some more
Yes, this is true; but the utils module could be provided as part of the course [1], and then it’s just two lines (or one with a semicolon, if you so choose). A lot of courses teach that you need to use if __name__ == "__main__" for your entrypoint, and by comparison, this is both less boilerplate AND easier to explain (“put this at the top of your script for that reminder when you edit the file”).
Actually, speaking of main modules, this exact feature would work for scripts too. If you put while True: .... input() .... in your script and edit it, you’d get a nice notification that your changes haven’t taken effect.
presumably with a better name, maybe related to the course, teacher, or institution ↩︎
Hmm. I would be inclined to not do that, because making a module truly reloadable requires some discipline, otherwise there’ll be some edge cases that are harder to get right. Definitely not impossible but it’s the sort of thing that I wouldn’t want thrust onto a novice.
Yeah, for something with a well-defined scope, it can often work quite well. A Flask app generally has (in effect) a single entry-point - the application object - so you can reload it, grab the new app object, and start feeding requests to it. You would still need to be careful of other features though - for example, if you spawn a thread, that thread will still run the old code.