6

現在Flaskで遊んでいますが、デバッグメカニズムがどのように機能しているかわかりません。より正確には、アプリケーションでPythonファイルを保存するときに、サーバーを再起動する必要はありません。リクエストを行うと、サーバーが自動的に読み込まれます。だから私の質問は、実行中のプログラムがそれが変更されたことをどのように認識し、その変更に応答するのかということです。

4

2 に答える 2

7

Flaskは、Werkzugの基礎となるrun_with_reloader関数(にありますserving.py)を使用しています...これ自体は、同じファイルで以前に作成され たrestart_with_reloaderand関数を使用しています。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
于 2010-12-22T22:43:15.610 に答える
0

組み込みreload()関数はあなたのためにこれを行うことができます。この関数は、Flaskがコードをリロードするために行うことの背後にある可能性があります(ディスク上で何らかの方法で変更されたことに気付いた後)。

質問Pythonモジュールをアンロード(リロード)するにはどうすればよいですか?これについての詳細があります。

于 2010-12-22T22:18:25.090 に答える