Skip to content

Instantly share code, notes, and snippets.

@alifarazz
Created November 19, 2017 13:39
Show Gist options
  • Save alifarazz/7dd8e07a9618b0055a15d55bac20fe0e to your computer and use it in GitHub Desktop.
Save alifarazz/7dd8e07a9618b0055a15d55bac20fe0e to your computer and use it in GitHub Desktop.
Watches a file, executes commands if the file is updated. (I use it for auto-compilation)
#!/usr/bin/env python3
# -*-coding:utf-8-*-
# usage:
# ./Watchdog.py <subfile> <commands>
# This script takes a <subfile> file and a list of <commands> which it immediately
# executes in a subprocess.
# It kills the subprocess and relaunches it whenever the file changes.
#
# If you accidentally introduce an error into the <subfile>, just fix that error
# and save the file again, and <commands> will be executed.
# Note that the subprocess shares the console with this process,
# therefore you will see its output.
import sys
import time
import subprocess
# import logging
import os
import watchdog
import watchdog.events
import watchdog.observers
import psutil
import signal
process = None
subfile = sys.argv[1]
command = ' '.join(sys.argv[2:])
def launch():
global process
process = subprocess.Popen(command, shell=True)
print("process with pid of {0} created".format(process.pid))
def samefile(a, b):
return os.stat(a) == os.stat(b)
def kill_or_do_nothing():
global process
try: # Process might already have terminated
process = psutil.Process(pid=process.pid)
for proc in process.children(recursive=True):
proc.kill()
process.kill()
except Exception as E:
print("couldn't destroy process, reason:\n\t",
str(E))
class Modified(watchdog.events.FileSystemEventHandler):
def on_modified(self, event):
if subfile not in event.src_path:
return
if not samefile(event.src_path, subfile):
return
print('<<', subfile, '>> modified, will restart\n')
kill_or_do_nothing()
launch()
class GracefulKiller():
kill_now = False
def __init__(self):
signal.signal(signal.SIGINT, self.exit_gracefully)
signal.signal(signal.SIGTERM, self.exit_gracefully)
def __str__(self):
print(self.kill_now)
def exit_gracefully(self, signum, frame):
self.kill_now = True
def main():
global killer
observer = watchdog.observers.Observer()
observer.schedule(Modified(), '.')
observer.start()
launch()
kill_or_do_nothing()
# Idle forever, listening on Modified.on_modified
while killer.kill_now is False:
time.sleep(1)
if __name__ == '__main__':
global killer
killer = GracefulKiller()
main()
print("Watchdog exited successfully")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment