Pythonソースコードを動的にロードします
質問
私は現在フラスコで遊んでいますが、デバッグメカニズムがどのように機能しているかを理解できません。アプリケーションでpythonファイルを保存する場合、より正確にするために、サーバーを再起動する必要はありません。リクエストを行うと自動的にロードされます。それで、私の質問は、ランニングプログラムがそれが変更されたことをどのように知っており、その変更に応答するのですか?
解決
FlaskはWerkzugの基礎を使用しています run_with_reloader
関数(にあります serving.py
)...それ自体を使用しています restart_with_reloader
と reloader_loop
同じファイルで早期に作成された関数。
run_with_reloader
別のPythonプロセスをスポーンします(最初のプロセスに渡したのと同じ引数でWerkzugを再度実行します)。 thread
サーバー機能を実行する新しいスレッドまたはサブプロセスを生成するモジュール。その後、実行します reloader_loop
そして待っています。
reloader_loop
インポートされ、最後の変更された日付を取得したすべてのモジュールをループするだけです。次に、指定された間隔(デフォルトで1秒)で、すべてのファイルをもう一度チェックして、それらが変更されたかどうかを確認します。彼らが持っている場合、現在実行されています(奴隷)werkzugプロセスは、3の出口コードで終了(終了)(終了します)。終了すると、スレッドまたはサブプロセスが開始され(実際に作業を行っています)、同様に終了します。 主人 出口コードが3であるかどうかを確認するためにチェックするプロセスチェックは、もしそうなら、新しいものが生まれます 奴隷 以前と同じように、サブプロセス。それ以外の場合、同じ出口コードで終了します。
参照のためのコードは次のとおりです。
def reloader_loop(extra_files=None, interval=1):
"""When this function is run from the main thread, it will force other
threads to exit when any modules currently loaded change.
Copyright notice. This function is based on the autoreload.py from
the CherryPy trac which originated from WSGIKit which is now dead.
:param extra_files: a list of additional files it should watch.
"""
def iter_module_files():
for module in sys.modules.values():
filename = getattr(module, '__file__', None)
if filename:
old = None
while not os.path.isfile(filename):
old = filename
filename = os.path.dirname(filename)
if filename == old:
break
else:
if filename[-4:] in ('.pyc', '.pyo'):
filename = filename[:-1]
yield filename
mtimes = {}
while 1:
for filename in chain(iter_module_files(), extra_files or ()):
try:
mtime = os.stat(filename).st_mtime
except OSError:
continue
old_time = mtimes.get(filename)
if old_time is None:
mtimes[filename] = mtime
continue
elif mtime > old_time:
_log('info', ' * Detected change in %r, reloading' % filename)
sys.exit(3)
time.sleep(interval)
def restart_with_reloader():
"""Spawn a new Python interpreter with the same arguments as this one,
but running the reloader thread.
"""
while 1:
_log('info', ' * Restarting with reloader...')
args = [sys.executable] + sys.argv
new_environ = os.environ.copy()
new_environ['WERKZEUG_RUN_MAIN'] = 'true'
# a weird bug on windows. sometimes unicode strings end up in the
# environment and subprocess.call does not like this, encode them
# to latin1 and continue.
if os.name == 'nt':
for key, value in new_environ.iteritems():
if isinstance(value, unicode):
new_environ[key] = value.encode('iso-8859-1')
exit_code = subprocess.call(args, env=new_environ)
if exit_code != 3:
return exit_code
def run_with_reloader(main_func, extra_files=None, interval=1):
"""Run the given function in an independent python interpreter."""
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
thread.start_new_thread(main_func, ())
try:
reloader_loop(extra_files, interval)
except KeyboardInterrupt:
return
try:
sys.exit(restart_with_reloader())
except KeyboardInterrupt:
pass
他のヒント
内蔵 reload()
関数はあなたのためにこれを行うことができます。この関数は、フラスコがコードをリロードするために行うことの背後にある可能性があります(何らかの方法でディスク上で変更されたことに気付いた後)。
質問 Pythonモジュールをアンロード(リロード)するにはどうすればよいですか? これに関する詳細情報があります。