Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added auto-reload to standalone server! Fixes #113. Thanks very much …

…to Jason Huggins for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@266 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 9566a61a22e1da30fb8abfef4b25d83d0c465be9 1 parent c21f6ec
@adrianholovaty adrianholovaty authored
Showing with 72 additions and 19 deletions.
  1. +22 −19 django/core/management.py
  2. +50 −0 django/utils/autoreload.py
View
41 django/core/management.py
@@ -419,27 +419,30 @@ def runserver(port):
"Starts a lightweight Web server for development."
from django.core.servers.basehttp import run, WSGIServerException
from django.core.handlers.wsgi import AdminMediaHandler, WSGIHandler
- from django.conf.settings import SETTINGS_MODULE
if not port.isdigit():
sys.stderr.write("Error: %r is not a valid port number.\n" % port)
sys.exit(1)
- print "Starting server on port %s with settings module %r." % (port, SETTINGS_MODULE)
- print "Go to http://127.0.0.1:%s/ for Django." % port
- print "Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows)."
- try:
- run(int(port), AdminMediaHandler(WSGIHandler()))
- except WSGIServerException, e:
- # Use helpful error messages instead of ugly tracebacks.
- ERRORS = {
- 13: "You don't have permission to access that port.",
- 98: "That port is already in use.",
- }
+ def inner_run():
+ from django.conf.settings import SETTINGS_MODULE
+ print "Starting server on port %s with settings module %r." % (port, SETTINGS_MODULE)
+ print "Go to http://127.0.0.1:%s/ for Django." % port
+ print "Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows)."
try:
- error_text = ERRORS[e.args[0].args[0]]
- except (AttributeError, KeyError):
- error_text = str(e)
- sys.stderr.write("Error: %s\n" % error_text)
- sys.exit(1)
- except KeyboardInterrupt:
- sys.exit(0)
+ run(int(port), AdminMediaHandler(WSGIHandler()))
+ except WSGIServerException, e:
+ # Use helpful error messages instead of ugly tracebacks.
+ ERRORS = {
+ 13: "You don't have permission to access that port.",
+ 98: "That port is already in use.",
+ }
+ try:
+ error_text = ERRORS[e.args[0].args[0]]
+ except (AttributeError, KeyError):
+ error_text = str(e)
+ sys.stderr.write("Error: %s\n" % error_text)
+ sys.exit(1)
+ except KeyboardInterrupt:
+ sys.exit(0)
+ from django.utils import autoreload
+ autoreload.main(inner_run)
runserver.args = '[optional port number]'
View
50 django/utils/autoreload.py
@@ -0,0 +1,50 @@
+# Autoreloading launcher.
+# Borrowed from Peter Hunt and the CherryPy project (http://www.cherrypy.org).
+# Some taken from Ian Bicking's Paste (http://pythonpaste.org/).
+
+import os, sys, thread, time
+
+RUN_RELOADER = True
+reloadFiles = []
+
+def reloader_thread():
+ mtimes = {}
+ while RUN_RELOADER:
+ for filename in filter(lambda v: v, map(lambda m: getattr(m, "__file__", None), sys.modules.values())) + reloadFiles:
+ if filename.endswith(".pyc"):
+ filename = filename[:-1]
+ mtime = os.stat(filename).st_mtime
+ if filename not in mtimes:
+ mtimes[filename] = mtime
+ continue
+ if mtime > mtimes[filename]:
+ sys.exit(3) # force reload
+ time.sleep(1)
+
+def restart_with_reloader():
+ while True:
+ args = [sys.executable] + sys.argv
+ if sys.platform == "win32":
+ args = ['"%s"' % arg for arg in args]
+ new_environ = os.environ.copy()
+ new_environ["RUN_MAIN"] = 'true'
+ exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ)
+ if exit_code != 3:
+ return exit_code
+
+def main(main_func, args=None, kwargs=None):
+ if os.environ.get("RUN_MAIN") == "true":
+ if args is None:
+ args = ()
+ if kwargs is None:
+ kwargs = {}
+ thread.start_new_thread(main_func, args, kwargs)
+ try:
+ reloader_thread()
+ except KeyboardInterrupt:
+ pass
+ else:
+ try:
+ sys.exit(restart_with_reloader())
+ except KeyboardInterrupt:
+ pass
Please sign in to comment.
Something went wrong with that request. Please try again.