twisted reloaded
twistedを使って開発してるひとがどれくらいいるかわかんないけど。
twistedを使ってると書き換えるたびいちいちサーバを再起動しないといけなかったりする。
djangoなんかは勝手に開発サーバが再起動されるので楽なのに><
いろいろ探したけどtwistedのautoreloadが見つからないので自分で書いてみた。
twisted.python.rebuildではとてもじゃないけど難しすぎ。
なのでWAITを使う。
参考にしたdjangoのautoreloadも元々はCherryPyのコードらしい。
CherryPy3.0からAutoReloadがサポートされてるんだけど同じ方式かな?
twistd_reload
#!/usr/bin/python from twisted.internet import reactor import sys, os, string, time if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1: sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir))) if hasattr(os, "getuid") and os.getuid() != 0: sys.path.insert(0, os.path.abspath(os.getcwd())) def reloader_thread(): mtimes = {} win = (sys.platform == "win32") while reactor.running: for filename in filter(lambda v: v, map(lambda m: getattr(m, "__file__", None), sys.modules.values())): if filename.endswith(".pyc") or filename.endswith("*.pyo"): filename = filename[:-1] if not os.path.exists(filename): continue # File might be in an egg, so it can't be reloaded. stat = os.stat(filename) mtime = stat.st_mtime if win: mtime -= stat.st_ctime if filename not in mtimes: mtimes[filename] = mtime continue if mtime != mtimes[filename]: def _stop(): reactor.stop() global reload reload = True reactor.callFromThread(_stop) 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 reload_support(main_func, args=None, kwargs=None): if os.environ.get("RUN_MAIN") == "true": if args is None: args = () if kwargs is None: kwargs = {} try: def _delay(): reactor.callInThread(reloader_thread) reactor.callLater(5, _delay) main_func(*args, **kwargs) except KeyboardInterrupt: pass else: try: sys.exit(restart_with_reloader()) except KeyboardInterrupt: pass from twisted.scripts.twistd import run reload_support(run) if reload: sys.exit(3) else: sys.exit(0)
つーか元ネタを考えたひとが偉いね!
元々のtwistdを拡張した形。
なのでtwistdの代わりに
twistd_reload -noy sample.tac
のようにするだけでよい。
tacファイルは何も意識せず普通に書けばいい。
例えばこんなん。
sample.tac
from twisted.application import service, strports from nevow import appserver import sample application = service.Application('sample') site = appserver.NevowSite(sample.SimplePage()) strports.service("8080", site).setServiceParent(application)
twistd_reloadで起動していると開発中のソースを保存するとサーバが勝手に再起動される。
んーつーかマジ便利だと思う!!
twisted用なのでこうなっているけど元ネタの方はどんな関数でもreload(再度呼び出し)することができる。
興味がある方はdjango.utils.autoreloadなどを見てみるといいです。
うくく。