国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 后端開發(fā) Python教程 django開發(fā)者模式中的autoreload是怎樣實(shí)現(xiàn)的

django開發(fā)者模式中的autoreload是怎樣實(shí)現(xiàn)的

Aug 19, 2017 pm 02:47 PM
django 開發(fā)者

? ? 在開發(fā)django應(yīng)用的過程中,使用開發(fā)者模式啟動服務(wù)是特別方便的一件事,只需要 python manage.py runserver 就可以運(yùn)行服務(wù),并且提供了非常人性化的autoreload機(jī)制,不需要手動重啟程序就可以修改代碼并看到反饋。剛接觸的時(shí)候覺得這個(gè)功能比較人性化,也沒覺得是什么特別高大上的技術(shù)。后來有空就想著如果是我來實(shí)現(xiàn)這個(gè)autoreload會怎么做,想了很久沒想明白,總有些地方理不清楚,看來第一反應(yīng)真是眼高手低了。于是就專門花了一些時(shí)間研究了django是怎樣實(shí)現(xiàn)autoreload的,每一步都看源碼說話,不允許有絲毫的想當(dāng)然:

1、runserver命令。在進(jìn)入正題之前其實(shí)有一大段廢話,是關(guān)于runserver命令如何執(zhí)行的,和主題關(guān)系不大,就簡單帶一下:
命令行鍵入 python manage.py runserver 后,django會去尋找runserver這個(gè)命令的執(zhí)行模塊,最后落在
django\contrib\staticfiles\management\commands\runserver.py模塊上:


#django\contrib\staticfiles\management\commands\runserver.pyfrom?django.core.management.commands.runserver?import?\
Command?as?RunserverCommandclass?Command(RunserverCommand):
  help?=?"Starts?a?lightweight?Web?server?for?development?and?also?serves?static?files."


而這個(gè)Command的執(zhí)行函數(shù)在這:


#django\core\management\commands\runserver.pyclass?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)


這里有關(guān)于use_reloader的判斷。如果我們在啟動命令中沒有加--noreload,程序就會走autoreload.main這個(gè)函數(shù),如果加了,就會走self.inner_run,直接啟動應(yīng)用。
其實(shí)從autoreload.main的參數(shù)也可以看出,它應(yīng)該是對self.inner_run做了一些封裝,autoreload的機(jī)制就在這些封裝當(dāng)中,下面我們繼續(xù)跟。

PS: 看源碼的時(shí)候發(fā)現(xiàn)django的command模式還是實(shí)現(xiàn)的很漂亮的,值得學(xué)習(xí)。

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做了區(qū)別處理,先忽略jpython;check_errors就是把對main_func進(jìn)行錯(cuò)誤處理,也先忽略??磒ython_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


第一次走到這里時(shí)候,環(huán)境變量中RUN_MAIN變量不是"true", 甚至都沒有,所以走else, 看restart_with_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


這里首先起一個(gè)while循環(huán), 內(nèi)部先把RUN_MAIN改成了"true",然后用os.spawnve方法開一個(gè)子進(jìn)程(subprocess),看看os.spawnve的說明:


  ?_spawnvef(mode,?file,?args,?env,?execve)


其實(shí)就是再調(diào)一遍命令行,又走了一遍 python manage.py runserver。

接著看restart_with_reloader里的while循環(huán),需要注意的是while循環(huán)退出的唯一條件是exit_code!=3。 如果子進(jìn)程不退出,就一直停在 os.spawnve這一步; 如果子進(jìn)程退出,而退出碼不是3,while就被終結(jié)了;如果是3,繼續(xù)循環(huán),重新創(chuàng)建子進(jìn)程。從這個(gè)邏輯可以猜想autoreload的機(jī)制:當(dāng)前進(jìn)程(主進(jìn)程)其實(shí)啥也不干,就監(jiān)視子進(jìn)程的運(yùn)行狀況,子進(jìn)程才是真正干事兒的;如果子進(jìn)程以exit_code=3退出(應(yīng)該由于檢測到了文件修改),就再啟動一遍子進(jìn)程,新代碼自然就生效了;如果子進(jìn)程以exit_code!=3退出,主進(jìn)程也結(jié)束,整個(gè)django程序就算跪了。這只是猜想,下面接著來驗(yàn)證。

3、子進(jìn)程。上面其實(shí)有一個(gè)疑問,既然是重新啟動了一次,為什么子進(jìn)程不會接著生成子進(jìn)程?原因就在于RUN_MAIN這個(gè)環(huán)境變量,主進(jìn)程中把它改成了true,子進(jìn)程走到python_reloader函數(shù)的時(shí)候:


#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條件滿足了,和主進(jìn)程走了不一樣的邏輯分支。在這里,首先去開一個(gè)線程,運(yùn)行main_func,就是上文的 Command.inner_run。這里的thread模塊是這么import的:


#django\utils\autoreload.py:from?django.utils.six.moves?import?_thread?as?thread


這里six模塊的作用是兼容各種python版本:


[codeblock?six]#django\utils\six.pyclass?_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"""官網(wǎng)說明:#?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.


所以如果程序想在python2和python3上都能跑,且魯邦,six是重要的工具。之后抽個(gè)時(shí)間看下six,mark一下。

然后再開一個(gè)reloader_thread:


===?change?==3)?    ?change?==1)


ensure_echo_on()其實(shí)還沒看明白,貌似是針對類unix系統(tǒng)文件處理的,先略過;
USE_INOTIFY也是系統(tǒng)文件操作相關(guān)的變量,根據(jù) inotify 是否可用選擇檢測文件變化的方法。
while循環(huán),每隔1秒檢測一下文件狀態(tài),如果是普通文件有變化,進(jìn)程退出,退出碼為3,主進(jìn)程一看:退出碼是3,就重啟子進(jìn)程。。。。這樣就和上面連上了;如果不是普通文件變化,而是I18N_MODIFIED(.mo后綴的文件變化,二進(jìn)制庫文件之類的),那就 reset_translations ,大概意思是把已加載過的庫緩存清理掉,下次重新加載。

  以上就是autoreload機(jī)制的流程。其中還是有些細(xì)節(jié)不是特別清楚,比如不同操作系統(tǒng)文件變化的檢測,但都是很細(xì)節(jié)的東西了,不涉及主流程。看完這些,我又問了自己一遍,如果是讓我設(shè)計(jì)autoreload機(jī)制會怎樣搞?,F(xiàn)在我的答案是:直接把 ?django\utils\autoreload.py 文件拿來用啊。其實(shí)這是很獨(dú)立的一個(gè)模塊,而且特別通用,完全可以作為通用的autoreload解決方案,我還自己寫個(gè)毛啊。

以上是django開發(fā)者模式中的autoreload是怎樣實(shí)現(xiàn)的的詳細(xì)內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

怎么看django版本 怎么看django版本 Dec 01, 2023 pm 02:25 PM

查看django版本步驟:1、打開終端或命令提示符窗口;2、確保已經(jīng)安裝了Django,如果沒有安裝Django,可以使用包管理工具來進(jìn)行安裝,輸入pip install django命令即可;3、安裝完成后,可以使用python -m django --version來查看Django的版本。

Django vs. Flask:Python Web框架的對比分析 Django vs. Flask:Python Web框架的對比分析 Jan 19, 2024 am 08:36 AM

Django和Flask都是PythonWeb框架中的佼佼者,它們都有著自己的優(yōu)點(diǎn)和適用場景。本文將對這兩個(gè)框架進(jìn)行對比分析,并提供具體的代碼示例。開發(fā)簡介Django是一個(gè)全功能的Web框架,它的主要目的是為了快速開發(fā)復(fù)雜的Web應(yīng)用。Django提供了許多內(nèi)置的功能,比如ORM(對象關(guān)系映射)、表單、認(rèn)證、管理后臺等。這些功能使得Django在處理大型

Django框架的優(yōu)點(diǎn)和缺點(diǎn):您需要知道的一切 Django框架的優(yōu)點(diǎn)和缺點(diǎn):您需要知道的一切 Jan 19, 2024 am 09:09 AM

Django是一個(gè)完整的開發(fā)框架,該框架涵蓋了Web開發(fā)生命周期的各個(gè)方面。目前,這個(gè)框架是全球范圍內(nèi)最流行的Web框架之一。如果你打算使用Django來構(gòu)建自己的Web應(yīng)用程序,那么你需要了解Django框架的優(yōu)點(diǎn)和缺點(diǎn)。以下是您需要知道的一切,包括具體代碼示例。Django優(yōu)點(diǎn):1.快速開發(fā)-Djang可以快速開發(fā)Web應(yīng)用程序。它提供了豐富的庫和內(nèi)

如何升級Django版本:步驟和注意事項(xiàng) 如何升級Django版本:步驟和注意事項(xiàng) Jan 19, 2024 am 10:16 AM

如何升級Django版本:步驟和注意事項(xiàng),需要具體代碼示例引言:Django是一個(gè)功能強(qiáng)大的PythonWeb框架,它持續(xù)地進(jìn)行更新和升級,以提供更好的性能和更多的功能。然而,對于使用較舊版本Django的開發(fā)者來說,升級Django可能會面臨一些挑戰(zhàn)。本文將介紹如何升級Django版本的步驟和注意事項(xiàng),并提供具體的代碼示例。一、備份項(xiàng)目文件在升級Djan

django版本區(qū)別是什么 django版本區(qū)別是什么 Nov 20, 2023 pm 04:33 PM

區(qū)別是:1、Django 1.x系列:這是Django的早期版本,包括1.0、1.1、1.2、1.3、1.4、1.5、1.6、1.7、1.8和1.9等版本。這些版本主要提供基本的Web開發(fā)功能;2、Django 2.x系列:這是Django的中期版本,包括2.0、2.1、2.2等版本;3、Django 3.x系列:這是Django的最新版本系列,包括3.0、3等版本。

天貓精靈云云接入服務(wù)升級:免費(fèi)開發(fā)者收費(fèi) 天貓精靈云云接入服務(wù)升級:免費(fèi)開發(fā)者收費(fèi) Jan 09, 2024 pm 10:06 PM

本站1月9日消息,天貓精靈日前發(fā)布云云接入服務(wù)升級的公告,升級后的云云接入服務(wù)從1月1日起從免費(fèi)模式變更為付費(fèi)。本站附新增功能和優(yōu)化:優(yōu)化云端協(xié)議,提升設(shè)備連接的穩(wěn)定性;優(yōu)化重點(diǎn)品類的語音控制;賬號授權(quán)升級:新增天貓精靈中開發(fā)者三方App的展示功能,幫助用戶更快更方便進(jìn)行賬號綁定,同時(shí)新增開發(fā)者三方App賬號授權(quán)支持一鍵綁定天貓精靈賬號;新增終端屏顯交互能力,除語音交互外,用戶可通過app、帶屏音箱控制設(shè)備、獲取設(shè)備狀態(tài);新增智能場景聯(lián)動能力,新建產(chǎn)品的屬性、事件,可作為狀態(tài)或事件上報(bào),定義天貓

怎么查看django版本 怎么查看django版本 Nov 30, 2023 pm 03:08 PM

查看django版本的方法:1、通過命令行查看,在終端或命令行窗口中輸入“python -m django --version”命令;2、在Python交互式環(huán)境中查看,輸入“import django print(django.get_version())”代碼;3、檢查Django項(xiàng)目的設(shè)置文件,找到名為INSTALLED_APPS的列表,其中包含已安裝的應(yīng)用程序信息。

Django是前端還是后端?一探究竟! Django是前端還是后端?一探究竟! Jan 19, 2024 am 08:37 AM

Django是一個(gè)Python編寫的web應(yīng)用框架,它強(qiáng)調(diào)快速開發(fā)和干凈方法。盡管Django是一個(gè)web框架,但是要回答Django是前端還是后端這個(gè)問題,需要深入理解前后端的概念。前端是指用戶直接和交互的界面,后端是指服務(wù)器端的程序,他們通過HTTP協(xié)議進(jìn)行數(shù)據(jù)的交互。在前端和后端分離的情況下,前后端程序可以獨(dú)立開發(fā),分別實(shí)現(xiàn)業(yè)務(wù)邏輯和交互效果,數(shù)據(jù)的交

See all articles