Эта статья основана на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, в противном случае он завершит всю программу.
Хорошо, поехали. Мы смело сделали первый шаг, продолжаем по следующей ссылке! ! !ヾ(◍°∇°◍)ノ゙