Some time ago, doing heavy-client dev (with kivy, check it out, it’s great!), i got bored with the save/run/quit/edit workflow, and having used flask and other tools with “–reload” like options, i wondered if there was something more generalistic.
I didn’t find anything, thought i didn’t search a lot, but i decided to scratch that itch, and to build a solution usable for about anything.
So after a few hours of hacking, i got a first version of an app reloader, using the watchdog lib, and some subprocess hacking. However the application was stealing the focus everytime it was started, wich made it a bit less fun to use. Another problem was there are a lot of events when you edit files (temporary files), and even when you save, a file editor as vim can produce as much as 8 events for only one save action. So a few options were added, and i think it’s now very usable.
For clarity, pythonar will use colors if possible (using the termcolor module if installed, and using colorama for windows compatibility if installed). So you should easily distinguish the events that trigger reloading of your app.
So here is a little presentation of what i called PythonAR, for Python Auto Reloader (althought it can be used for any apps, not just python ones):
Assume you are editing a few files with vim, and want to restart your python app when you save any file, the base configuration for that would be :
reload python my_app.py
But you’ll run into a few issues, first, vim will create swapfiles, that will be changed after about everytime you touch your keyboard, let’s ignore those files.
reload -i *.sw* ./my_app.py
Now, when your app will start, it will often create .pyc or .pyo files, we can ignore them too :
reload -i *.sw* *.py. ./my_app.py
We’ll soon discover it’s not enought, thought, what happens when vim save a file is not a single operation, first vim test if it can write in the folder, creating a file named “4913″, and delete it, then it moves the files it want to save to a backup, create a new file, modify it, and delete the backup. That would trigger way to much restarts to be comfortable with. Filtering with -i, as we did before can only lower that to two restarts, because two events are happening on the real filename we want, so another option is needed.
the “-s” (or “–sleep”) option, will prevent any event to trigger a reload for the number of seconds. That will resolve this problem.
reload -i *.sw* *.py. -s 1 ./my_app.py
For graphical applications, most window managers will pass the focus to the newly created window each time it is restarted, this can be a serious distraction. The solution here is not perfect, and probably won’t work out of Linux (patches welcome, thought ^^). The “-f” (or “–focus”) option, will prevent the wm from changing the focused application for at least a few seconds, effectively preventing the new window to steal the focus. Unfortulatly, this depend on “xdotool“ an utility based on the xlib, so only useful on X. Any solution for window or OSx appreciated.
reload -i *.sw* *.py. -s 1 -f 3 ./my_app.py
Whatsmore, the -p (”–path”) allow to monitor a different folder than the current one. And the “-a” (or “–action”) is reserved for potential future actions, the default and currently only available value is “restart”.
Yeah, that’s quite a lot of options, i think the next useful addition would be some config parser use, to save options for a project in a simple ini file.
That’s it :) i hope it will be useful to people. The project is hosted on Github, as most of the stuff i do nowadays :).