Here is an example of how this can be implemented using pyinotify (i.e. on Linux).
from importlib import import_module class RestartingLauncher: def __init__(self, module_name, start_function, stop_function, path="."): self._module_name = module_name self._filename = '%s.py' % module_name self._start_function = start_function self._stop_function = stop_function self._path = path self._setup() def _setup(self): import pyinotify self._wm = pyinotify.WatchManager() self._notifier = pyinotify.ThreadedNotifier( self._wm, self._on_file_modified) self._notifier.start()
The parameters in the launch_app call are the file name (without ".py"), a function to start execution, and a function that somehow stops the execution.
Here is a silly example of an “application” that can be overwritten using the previous code:
run = True def main(): print 'in...' while run: pass print 'out' def force_exit(): global run run = False
In a typical application where you want to use this, you will probably have some kind of main loop. Here's a more realistic example for a GLib / GTK + application:
from gi.repository import GLib GLib.threads_init() loop = GLib.MainLoop() def main(): print "running..." loop.run() def force_exit(): print "stopping..." loop.quit()
The same concept works for most other loops (Clutter, Qt, etc.).
Monitoring multiple code files (i.e. all files that are part of the application) and error tolerance (for example, printing exceptions and idle wait until the code is fixed and then run it again) will remain as exercises for the reader :).
Note. All of the code in this answer is released under the ISC license (in addition to Creative Commons).
source share