1

我正在使用 webapp2 进行 Web 开发。在我的开发环境中,如何让它自动重新加载代码更改?我正在使用httpserver.serve(app, host='127.0.0.1', port='8008'),但每次更改代码时,我都需要停止服务器并重新启动它。

我已经将 webapp2 与 Google 提供的 Google App Engine 启动器一起使用,并且每次进行更改时都不需要重新启动它。他们是怎么做到的呢?他们是否监视文件系统更改并reload在发生更改时调用模块?

4

2 回答 2

1

事实证明,谷歌提供的谷歌应用引擎启动器是从 Django 框架中借用自动重载代码,特别是这个:https ://github.com/django/django/blob/master/django/utils/autoreload.py

搜索了 Stackoverflow 并有一些相关的问题提供了答案: 如何在文件更改时自动重新加载 Django? 它又链接到这个模块,该模块能够检测和重新加载更改的代码:https ://github.com/tjwalch/django-livereload-server

如果有人想详细了解我是如何做到的。

在我的启动器中:

import autoreloader,thread
thread.start_new_thread(autoreloader.reloader_thread, ())
...
app = webapp2.WSGIApplication(...)
def main():
    from paste import httpserver
    httpserver.serve(app, ...)

自动重载器.py:

import sys,os,time,logging

RUN_RELOADER = True

logger = logging.getLogger(__name__)

whitelist = ['webapp2', 'paste', 'logging']

# this code is from autoreloader
_mtimes = {}
_win = (sys.platform == "win32")
_error_files = []
_cached_modules = set()
_cached_filenames = []


def gen_filenames(only_new=False):
    global _cached_modules, _cached_filenames
    module_values = set(sys.modules.values())
    _cached_filenames = clean_files(_cached_filenames)
    if _cached_modules == module_values:
        # No changes in module list, short-circuit the function
        if only_new:
            return []
        else:
            return _cached_filenames + clean_files(_error_files)

    new_modules = module_values - _cached_modules
    new_filenames = clean_files(
        [filename.__file__ for filename in new_modules
         if hasattr(filename, '__file__')])

    _cached_modules = _cached_modules.union(new_modules)
    _cached_filenames += new_filenames
    if only_new:
        return new_filenames + clean_files(_error_files)
    else:
        return _cached_filenames + clean_files(_error_files)

def clean_files(filelist):
    filenames = []
    for filename in filelist:
        if not filename:
            continue
        if filename.endswith(".pyc") or filename.endswith(".pyo"):
            filename = filename[:-1]
        if filename.endswith("$py.class"):
            filename = filename[:-9] + ".py"
        if os.path.exists(filename):
            filenames.append(filename)
    return filenames

# this code is modified from autoreloader
def check_code_changed():
    global _mtimes, _win
    for filename in gen_filenames():
        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]:
            _mtimes = {}
            try:
                del _error_files[_error_files.index(filename)]
            except ValueError:
                pass
            mname = filename.split('/')[-1].split('.')[0]
            logger.info('CHANGED %s, RELOADING %s' % (filename,mname))
            try:
                reload(sys.modules[mname])
            except:
                pass

    return False

def reloader_thread():
    while RUN_RELOADER:
        check_code_changed()
        time.sleep(1)
于 2016-05-23T22:08:16.247 回答
0

粘贴有自己的自动重新加载功能(可能在提供原始答案时它不存在)..

app = webapp2.WSGIApplication(...)
def main():
    from paste import httpserver, reload
    reload.install()
    httpserver.serve(app, ...)

然后使用 Paste 提供的 shell 脚本启动你的服务器:

err=3
while test "$err" -eq 3 ; do
    python server.py
    err="$?"
done

现在,每次您在项目中编辑文件时,服务器都会自动重新加载。

参考文档:

于 2020-06-25T12:05:11.303 回答