Эта статья основана наdjango-2.1.x
Серия версий написана.
Начальный тест - после изменения файлаserver
автоматический перезапуск
Перед этим давайте разбираться
django
Как сделать автоматический перезапуск
Начинать
django
использоватьrunserver
При выполнении команды запускаются два процесса.
runserver
В основном называетсяdjango/utils/autoreload.py
Внизmain
метод.
Что касается того, почему мы пришли сюда, мы не будем здесь вдаваться в подробности и объясним это в следующих главах.
основная нить черезos.stat
Метод получает время последней модификации файла для сравнения, а затем перезапускаетсяdjango
Службы (они же дочерние процессы).
Мониторинг примерно раз в секунду.
# django/utils/autoreload.py 的 reloader_thread 方法
def reloader_thread():
...
# 监听文件变化
# -- Start
# 这里主要使用了 `pyinotify` 模块,因为目前可能暂时导入不成功,使用 else 块代码
# USE_INOTIFY 该值为 False
if USE_INOTIFY:
fn = inotify_code_changed
else:
fn = code_changed
# -- End
while RUN_RELOADER:
change = fn()
if change == FILE_MODIFIED:
sys.exit(3) # force reload
elif change == I18N_MODIFIED:
reset_translations()
time.sleep(1)
code_changed
Возвращает в зависимости от того, изменилось ли лучшее время модификации каждого файлаTrue
достичь цели перезапуска.
Родительско-дочерний процесс и многопоточность
Код для перезагрузки находится вpython_reloader
внутри функции
# django/utils/autoreload.py
def restart_with_reloader():
import django.__main__
while True:
args = [sys.executable] + ['-W%s' % o for o in sys.warnoptions]
if sys.argv[0] == django.__main__.__file__:
# The server was started with `python -m django runserver`.
args += ['-m', 'django']
args += sys.argv[1:]
else:
args += sys.argv
new_environ = {**os.environ, 'RUN_MAIN': 'true'}
exit_code = subprocess.call(args, env=new_environ)
if exit_code != 3:
return exit_code
def python_reloader(main_func, args, kwargs):
# 一开始环境配置是没有该变量的,所有走的是 else 语句块
if os.environ.get("RUN_MAIN") == "true":
# 开启一个新的线程启动服务
_thread.start_new_thread(main_func, args, kwargs)
try:
# 程序接着向下走,监控文件变化
# 文件变化,退出该进程,退出码反馈到了 subprocess.call 接收处...
reloader_thread()
except KeyboardInterrupt:
pass
else:
try:
# 而在 restart_with_reloader 这个函数设置了 RUN_MAIN 变量
exit_code = restart_with_reloader()
if exit_code < 0:
os.kill(os.getpid(), -exit_code)
else:
sys.exit(exit_code)
except KeyboardInterrupt:
pass
программа запускается, потому что нетRUN_MAIN
переменная, поэтому перейдите к блоку else.
Достаточно интересно,restart_with_reloader
используется в функцииsubprocess.call
метод выполняет команду для запуска программы (например, python3 manage.py runserver), в данный моментRUN_MAIN
ценностьTrue
, затем выполните_thread.start_new_thread(main_func, args, kwargs)
Открытие новой темы означает началоdjango
Служить.
Если дочерний процесс не завершается, он остается вcall
Метод здесь (для обработки запроса), если дочерний процесс завершается, код выхода не 3, то время завершается. В противном случае цикл продолжается, и дочерний процесс создается заново.
Обнаружение модификаций файлов
Реализация функции, специально обнаруживающей изменения в файле.
# django/utils/autoreload.py
def code_changed():
global _mtimes, _win
# 获取所有文件
for filename in gen_filenames():
# 通过 os 模块查看每个文件的状态
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
return I18N_MODIFIED if filename.endswith('.mo') else FILE_MODIFIED
return False
Суммировать
Вышеупомянутоеdjango
Обнаружение модификации файла для достижения процесса реализации перезапуска службы.
комбинироватьsubprocess.call
и переменные среды для создания двух процессов. Основной процесс отвечает за мониторинг дочерних процессов и перезапуск дочерних процессов.
Запустив новый поток в дочернем процессе (т.django
Служить). Основной поток отслеживает изменения файла и, если он изменяется, передаетsys.exit(3)
Чтобы выйти из дочернего процесса, родительский процесс продолжит создание дочернего процесса, если код выхода не равен 3, в противном случае он завершит всю программу.
Хорошо, поехали. Мы смело сделали первый шаг, продолжаем по следующей ссылке! ! !ヾ(◍°∇°◍)ノ゙