Last active
July 4, 2022 13:35
-
-
Save Twilight0/7021035f2940eaa2084c9547866cd5a1 to your computer and use it in GitHub Desktop.
Hot reload a python working script (compatible with both python 2 & 3)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from __future__ import print_function | |
import sys, os, time, threading, subprocess, fnmatch | |
class SourceChangeMonitor(threading.Thread): | |
# Remember the process ID of the subprocess for when | |
# we want to restart it | |
_process = None | |
# How often should we check for changes (in seconds) | |
POLL_INTERVAL = 1 | |
# Which files should be monitored for changes? | |
# Here, we deliberately exclude files beginning with a dot (.) | |
FILE_PATTERN = r"[!.]*.py" | |
# Which directory is the root of the source files? | |
ROOT_DIRECTORY = r"/type/script/path/here/" | |
# Entry point program to run | |
PROGRAM = r"name_of_script.py" | |
def __init__(self): | |
threading.Thread.__init__(self) | |
self.this_script_name = os.path.abspath(sys.argv[0]) | |
self.files = self.get_files() | |
self.start_program() | |
def run(self): | |
while 1: | |
time.sleep(self.POLL_INTERVAL) | |
if self.poll(): | |
print("-------------------------------------------------") | |
print("Noticed a change in program source. Restarting...") | |
print("-------------------------------------------------") | |
self.start_program() | |
def get_files(self): | |
""" | |
Get a list of all files along with their timestamps for last modified | |
""" | |
files = [] | |
for root, dirnames, filenames in os.walk(self.ROOT_DIRECTORY): | |
for filename in fnmatch.filter(filenames, self.FILE_PATTERN): | |
full_filename = os.path.join(root, filename) | |
files.append(full_filename) | |
# Attach the last modified dates | |
files = map(lambda f: (f, os.stat(f).st_mtime), files) | |
files = [filename_mtime for filename_mtime in files if filename_mtime[0] != self.this_script_name] | |
return files | |
def poll(self): | |
"""Check if any source files have changed since last poll. Returns True if files have changed, False otherwise""" | |
new_files = self.get_files() | |
if self.files != new_files: | |
self.files = new_files | |
return True | |
return False | |
def start_program(self): | |
"""Start the program. If it was already started, kill it before restarting""" | |
if self._process != None and self._process.poll() is None: | |
self._process.kill() | |
self._process.wait() | |
self._process = subprocess.Popen([sys.executable, self.PROGRAM]) | |
if __name__ == "__main__": | |
SourceChangeMonitor().start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment