python autoreload
autoreloadに関して少し勉強。Cherrypyを参考にしていたんだけど、前と今ではちょっと処理が違うみたい。
前の処理はhttp://d.hatena.ne.jp/Wacky/20060820/1156050077に書いてあるように、子プロセスが実行プロセスで、親プロセスが管理プロセスの役割を果たしているみたい。
だけど、CherryPy3.0.3からはautoreload.pyがなくなって_cpengine.pyにautoreload関数がある。これがファイル数ごとに
reexec()を行っている感じ。
def autoreload(self): """Reload the process if registered files have been modified.""" sysfiles = [] for k, m in sys.modules.items(): if re.match(self.autoreload_match, k): if hasattr(m, "__loader__"): if hasattr(m.__loader__, "archive"): k = m.__loader__.archive k = getattr(m, "__file__", None) sysfiles.append(k) for filename in sysfiles + self.reload_files: if filename: if filename.endswith(".pyc"): filename = filename[:-1] oldtime = self.mtimes.get(filename, 0) if oldtime is None: # Module with no .py file. Skip it. continue try: mtime = os.stat(filename).st_mtime except OSError: # Either a module with no .py file, or it's been deleted. mtime = None if filename not in self.mtimes: # If a module has no .py file, this will be None. self.mtimes[filename] = mtime else: if mtime is None or mtime > oldtime: # The file has been deleted or modified. self.reexec()
reexecは一度サーバーを停止させて、諸設定をした後にexecvを行ってる。そっか、新しい方では一つのプロセスで自動リロードをすませているのか。
def reexec(self): """Re-execute the current process.""" cherrypy.server.stop() self.stop() args = sys.argv[:] cherrypy.log("Re-spawning %s" % " ".join(args), "ENGINE") args.insert(0, sys.executable) if sys.platform == "win32": args = ['"%s"' % arg for arg in args] # Some platforms (OS X) will error if all threads are not # ABSOLUTELY terminated. See http://www.cherrypy.org/ticket/581. for trial in xrange(self.reexec_retry * 10): try: os.execv(sys.executable, args) return except OSError, x: if x.errno != 45: raise time.sleep(0.1) else: raise