django 개발 자 모드 의 autoreload 가 어떻게 실현 되 었 는 지 에 대해 말씀 드 리 겠 습 니 다.
8680 단어 djangoautoreload
1.runserver 명령.본론 으로 들 어가 기 전에 runserver 명령 을 어떻게 실행 하 는 지 에 관 한 쓸데없는 말 이 있 습 니 다.주제 와 관계 가 크 지 않 으 므 로 간단하게 가 져 가 겠 습 니 다.
명령 행 이 python manage.py runserver 를 입력 하면 django 는 runserver 라 는 명령 의 실행 모듈 을 찾 아 마지막 으로 떨 어 집 니 다.
django\\contrib\staticfiles\\management\\commands\\runserver.py 모듈 에서:
#django\contrib\staticfiles\management\commands\runserver.py
from django.core.management.commands.runserver import \
Command as RunserverCommand
class Command(RunserverCommand):
help = "Starts a lightweight Web server for development and also serves static files."
이 command 의 실행 함 수 는 다음 과 같 습 니 다:
#django\core\management\commands\runserver.py
class Command(BaseCommand):
def run(self, **options):
"""
Runs the server, using the autoreloader if needed
"""
use_reloader = options['use_reloader']
if use_reloader:
autoreload.main(self.inner_run, None, options)
else:
self.inner_run(None, **options)
여기 usereloader 의 판단.만약 우리 가 시작 명령 에-noreload 를 추가 하지 않 았 다 면,프로그램 은 autoreload.main 이라는 함 수 를 가 고,추가 하면 self.inner 를 갈 것 입 니 다.run,응용 프로그램 을 직접 시작 합 니 다.사실 autoreload.main 의 매개 변수 에서 도 알 수 있 듯 이 self.innerrun 은 패 키 지 를 만 들 었 습 니 다.autoreload 의 체 제 는 바로 이 패 키 지 를 통 해 다음 과 같 습 니 다.
PS:원본 코드 를 보 았 을 때 django 의 command 모드 가 여전히 아름 답 게 실현 되 었 음 을 발 견 했 습 니 다.배 울 만 한 가치 가 있 습 니 다.
2.autoreload 모듈.autoreload.main()보기:
#django\utils\autoreload.py:
def main(main_func, args=None, kwargs=None):
if args is None:
args = ()
if kwargs is None:
kwargs = {}
if sys.platform.startswith('java'):
reloader = jython_reloader
else:
reloader = python_reloader
wrapped_main_func = check_errors(main_func)
reloader(wrapped_main_func, args, kwargs)
jpython 과 다른 python 에 대해 구별 처 리 를 했 습 니 다.먼저 jpython 을 무시 합 니 다.check_errors 는 mainfunc 오류 처리 도 무시 합 니 다.python 보기reloader:
#django\utils\autoreload.py:
def python_reloader(main_func, args, kwargs):
if os.environ.get("RUN_MAIN") == "true":
thread.start_new_thread(main_func, args, kwargs)
try:
reloader_thread()
except KeyboardInterrupt:
pass
else:
try:
exit_code = restart_with_reloader()
if exit_code < 0:
os.kill(os.getpid(), -exit_code)
else:
sys.exit(exit_code)
except KeyboardInterrupt:
pass
처음 여기까지 왔 을 때 환경 변수 중 RUNMAIN 변 수 는"true"가 아니 라 심지어 없습니다.그 러 니까 else 로 가세 요.restartwith_reloader:
#django\utils\autoreload.py:
def restart_with_reloader():
while True:
args = [sys.executable] + ['-W%s' % o for o in sys.warnoptions] + sys.argv
if sys.platform == "win32":
args = ['"%s"' % arg for arg in args]
new_environ = os.environ.copy()
new_environ["RUN_MAIN"] = 'true'
exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ)
if exit_code != 3:
return exit_code
여기 서 먼저 while 순환 을 하고 내 부 는 RUNMAIN 은"true"로 바 뀌 었 습 니 다.그리고 os.spawnve 방법 으로 키 프로 세 스(subprocess)를 엽 니 다.os.spawnve 의 설명 을 보 세 요.
#os.py
def spawnve(mode, file, args, env):
"""spawnve(mode, file, args, env) -> integer
Execute file with arguments from args in a subprocess with the
specified environment.
If mode == P_NOWAIT return the pid of the process.
If mode == P_WAIT return the process's exit code if it exits normally;
otherwise return -SIG, where SIG is the signal that killed it. """
return _spawnvef(mode, file, args, env, execve)
사실은 명령 행 을 다시 한 번 바 꾸 고 python manage.py runserver 를 다시 한 번 걸 었 습 니 다.이어서 restartwith_reloader 의 while 순환,주의해 야 할 것 은 while 순환 종료 의 유일한 조건 은 exit 입 니 다.code!=3。 하위 프로 세 스 가 종료 되 지 않 으 면 os.spawnve 에서 계속 멈 춥 니 다.하위 프로 세 스 가 종료 되 고 종료 코드 가 3 이 아니라면 while 는 종 료 됩 니 다.3 이면 계속 순환 하고 하위 프로 세 스 를 다시 만 듭 니 다.이 논리 에서 autoreload 의 메커니즘 을 추측 할 수 있 습 니 다.현재 프로 세 스(주 프로 세 스)는 아무것도 하지 않 고 하위 프로 세 스 의 운행 상황 을 감시 합 니 다.하위 프로 세 스 가 야 말로 진정한 일 입 니 다.하위 프로 세 스 가 exit 로code=3 종료(파일 수정 이 감지 되 었 기 때문에)하위 프로 세 스 를 다시 시작 하면 새 코드 가 자 연 스 럽 게 유효 합 니 다.하위 프로 세 스 가 exit 로code!=3.종료 하면 메 인 프로 세 스 도 끝 납 니 다.전체 django 프로그램 은 무릎 을 꿇 어도 됩 니 다.이것 은 단지 추측 일 뿐 이 니,다음은 이어서 검증 하 자.
3.하위 프로 세 스.위 에 사실 한 가지 의문 이 있 습 니 다.다시 시작 한 이상 왜 하위 프로 세 스 가 하위 프로 세 스 를 계속 만 들 지 않 습 니까?그 이 유 는 RUNMAIN 이 환경 변 수 는 메 인 프로 세 스에 서 true 로 바 뀌 었 습 니 다.하위 프로 세 스 는 python 으로 갑 니 다.reloader 함수 일 때:
#django\utils\autoreload.py:
def python_reloader(main_func, args, kwargs):
if os.environ.get("RUN_MAIN") == "true":
thread.start_new_thread(main_func, args, kwargs)
try:
reloader_thread()
except KeyboardInterrupt:
pass
else:
try:
exit_code = restart_with_reloader()
if exit_code < 0:
os.kill(os.getpid(), -exit_code)
else:
sys.exit(exit_code)
except KeyboardInterrupt:
pass
if 조건 이 만족 하면 메 인 프로 세 스 와 다른 논리 적 가 지 를 가 집 니 다.여기 서 먼저 스 레 드 를 열 고 main 을 실행 합 니 다.func,바로 위의 command.innerrun。여기 thread 모듈 은 이렇게 import 입 니 다:
#django\utils\autoreload.py:
from django.utils.six.moves import _thread as thread
여기 six 모듈 의 역할 은 각종 python 버 전 을 호 환 하 는 것 입 니 다.
[codeblock six]
#django\utils\six.py
class _SixMetaPathImporter(object):
"""
A meta path importer to import six.moves and its submodules.
This class implements a PEP302 finder and loader. It should be compatible
with Python 2.5 and all existing versions of Python3
"""
:
# https://pythonhosted.org/six/
Six: Python 2 and 3 Compatibility Library
Six provides simple utilities for wrapping over differences between Python 2 and Python 3. It is intended to support codebases that work on both Python 2 and 3 without modification. six consists of only one Python file, so it is painless to copy into a project.
그래서 프로그램 이 python 2 와 python 3 에서 모두 뛸 수 있 고 노 방,six 는 중요 한 도구 입 니 다.그리고 시간 을 내 서 six,mark 를 보 세 요.그리고 다시 reloaderthread:
[codeblock autoreload_reloader_thread]
#django\utils\autoreload.py:
def reloader_thread():
ensure_echo_on()
if USE_INOTIFY:
fn = inotify_code_changed
else:
fn = code_changed
while RUN_RELOADER:
change = fn()
if change == FILE_MODIFIED:
sys.exit(3) # force reload
elif change == I18N_MODIFIED:
reset_translations()
time.sleep(1)
ensure_echo_on()사실 아직 잘 모 르 겠 습 니 다.유 닉 스 시스템 파일 을 대상 으로 처리 한 것 같 습 니 다.먼저 생략 한 것 같 습 니 다.USE_INOTIFY 도 시스템 파일 작업 과 관련 된 변수 로 inotify 가 파일 변 화 를 감지 하 는 방법 을 선택 할 수 있 는 지 여부 에 따라 선택 할 수 있 습 니 다.
while 순환,1 초 간격 으로 파일 상 태 를 검사 합 니 다.일반 파일 에 변화 가 있 으 면 프로 세 스 가 종료 되 고 종료 코드 는 3 입 니 다.메 인 프로 세 스 를 보 니 종료 코드 가 3 이면 하위 프로 세 스 를 다시 시작 합 니 다.이렇게 하면 위 와 연결된다.일반 파일 변화 가 아니 라 I18NMODIFIED(.mo 접미사 의 파일 변화,바 이 너 리 라 이브 러 리 파일 등),resettranslations,불 러 온 라 이브 러 리 캐 시 를 지우 고 다음 에 다시 불 러 오 라 는 뜻 입 니 다.
이상 은 autoreload 메커니즘 의 절차 입 니 다.그 중에서 일부 세부 사항 은 잘 모 르 겠 습 니 다.예 를 들 어 서로 다른 운영 체제 파일 변화 에 대한 검 측 이지 만 모두 세부 적 인 것 이 고 주류 과정 과 관련 되 지 않 습 니 다.이것 을 보고 나 는 또 나 에 게 autoreload 체 제 를 설계 하 라 고 하면 어떻게 할 것 이 냐 고 물 었 다.지금 내 대답 은 django\utils\autoreload.py 파일 을 직접 가 져 와 서 사용 하 는 거 야.사실 이것 은 매우 독립 된 모듈 이 고 특히 통용 되 며 통용 되 는 autoreload 솔 루 션 으로 충분히 사용 할 수 있 습 니 다.저 는 스스로 털 도 쓸 수 있 습 니 다.
django 개발 자 모드 의 autoreload 가 어떻게 실현 되 었 는 지 에 대한 간단 한 이 야 기 는 바로 편집장 이 여러분 에 게 공유 한 모든 내용 입 니 다.여러분 께 참고 가 되 고 저 희 를 많이 사랑 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Django의 질문 및 답변 웹사이트환영 친구, 이것은 우리의 새로운 블로그입니다. 이 블로그에서는 , 과 같은 Question-n-Answer 웹사이트를 만들고 있습니다. 이 웹사이트는 회원가입 및 로그인이 가능합니다. 로그인 후 사용자는 사용자의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.