1 | # autoreloading launcher
|
---|
2 | # borrowed from the Peter Hunt and the CherryPy project (www.cherrypy.org)
|
---|
3 | # from code that was borrowed from Ian Bicking's Paste (http://pythonpaste.org/)
|
---|
4 |
|
---|
5 |
|
---|
6 | import os
|
---|
7 | import sys
|
---|
8 | import time
|
---|
9 | import thread
|
---|
10 |
|
---|
11 | RUN_RELOADER = True
|
---|
12 | reloadFiles = []
|
---|
13 |
|
---|
14 | def reloader_thread():
|
---|
15 | mtimes = {}
|
---|
16 | while RUN_RELOADER:
|
---|
17 | for filename in filter(lambda v: v, map(lambda m: getattr(m, "__file__", None), sys.modules.values())) + reloadFiles:
|
---|
18 | if filename.endswith(".pyc"):
|
---|
19 | filename = filename[:-1]
|
---|
20 | mtime = os.stat(filename).st_mtime
|
---|
21 | if filename not in mtimes:
|
---|
22 | mtimes[filename] = mtime
|
---|
23 | continue
|
---|
24 | if mtime > mtimes[filename]:
|
---|
25 | sys.exit(3) # force reload
|
---|
26 | time.sleep(1)
|
---|
27 |
|
---|
28 | def restart_with_reloader():
|
---|
29 | while True:
|
---|
30 | args = [sys.executable] + sys.argv
|
---|
31 | if sys.platform == "win32": args = ['"%s"' % arg for arg in args]
|
---|
32 | new_environ = os.environ.copy()
|
---|
33 | new_environ["RUN_MAIN"] = 'true'
|
---|
34 | exit_code = os.spawnve(os.P_WAIT, sys.executable,
|
---|
35 | args, new_environ)
|
---|
36 | if exit_code != 3:
|
---|
37 | return exit_code
|
---|
38 |
|
---|
39 | def main(main_func, args=None, kwargs=None):
|
---|
40 | if os.environ.get("RUN_MAIN") == "true":
|
---|
41 |
|
---|
42 | if args is None:
|
---|
43 | args = ()
|
---|
44 | if kwargs is None:
|
---|
45 | kwargs = {}
|
---|
46 | thread.start_new_thread(main_func, args, kwargs)
|
---|
47 |
|
---|
48 | try:
|
---|
49 | reloader_thread()
|
---|
50 | except KeyboardInterrupt:
|
---|
51 | pass
|
---|
52 | else:
|
---|
53 | try:
|
---|
54 | sys.exit(restart_with_reloader())
|
---|
55 | except KeyboardInterrupt:
|
---|
56 | print "<Ctrl-C> hit: shutting down autoreloader"
|
---|