? ? 在開發(fā)django應(yīng)用的過程中,使用開發(fā)者模式啟動服務(wù)是特別方便的一件事,只需要 python manage.py runserver 就可以運(yùn)行服務(wù),并且提供了非常人性化的autoreload機(jī)制,不需要手動重啟程序就可以修改代碼并看到反饋。剛接觸的時候覺得這個功能比較人性化,也沒覺得是什么特別高大上的技術(shù)。后來有空就想著如果是我來實(shí)現(xiàn)這個autoreload會怎么做,想了很久沒想明白,總有些地方理不清楚,看來第一反應(yīng)真是眼高手低了。于是就專門花了一些時間研究了django是怎樣實(shí)現(xiàn)autoreload的,每一步都看源碼說話,不允許有絲毫的想當(dāng)然:
1、runserver命令。在進(jìn)入正題之前其實(shí)有一大段廢話,是關(guān)于runserver命令如何執(zhí)行的,和主題關(guān)系不大,就簡單帶一下:
命令行鍵入 python manage.py runserver 后,django會去尋找runserver這個命令的執(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."
而這個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這個函數(shù),如果加了,就會走self.inner_run,直接啟動應(yīng)用。
其實(shí)從autoreload.main的參數(shù)也可以看出,它應(yīng)該是對self.inner_run做了一些封裝,autoreload的機(jī)制就在這些封裝當(dāng)中,下面我們繼續(xù)跟。
PS: 看源碼的時候發(fā)現(xiàn)django的command模式還是實(shí)現(xiàn)的很漂亮的,值得學(xué)習(xí)。
2、autoreload模塊??碼utoreload.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)行錯誤處理,也先忽略??磒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
第一次走到這里時候,環(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
這里首先起一個while循環(huán), 內(nèi)部先把RUN_MAIN改成了"true",然后用os.spawnve方法開一個子進(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)程。從這個邏輯可以猜想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é)束,整個django程序就算跪了。這只是猜想,下面接著來驗(yàn)證。
3、子進(jìn)程。上面其實(shí)有一個疑問,既然是重新啟動了一次,為什么子進(jìn)程不會接著生成子進(jìn)程?原因就在于RUN_MAIN這個環(huán)境變量,主進(jìn)程中把它改成了true,子進(jìn)程走到python_reloader函數(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)程走了不一樣的邏輯分支。在這里,首先去開一個線程,運(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是重要的工具。之后抽個時間看下six,mark一下。
然后再開一個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ú)立的一個模塊,而且特別通用,完全可以作為通用的autoreload解決方案,我還自己寫個毛啊。
Atas ialah kandungan terperinci django開發(fā)者模式中的autoreload是怎樣實(shí)現(xiàn)的. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Langkah-langkah untuk menyemak versi Django: 1. Buka terminal atau tetingkap command prompt 2. Pastikan Django tidak dipasang, anda boleh menggunakan alat pengurusan pakej untuk memasangnya dan masukkan perintah pip install django; Selepas pemasangan selesai, anda boleh menggunakan python -m django --version untuk menyemak versi Django.

Django ialah rangka kerja pembangunan lengkap yang merangkumi semua aspek kitaran hayat pembangunan web. Pada masa ini, rangka kerja ini merupakan salah satu rangka kerja web yang paling popular di seluruh dunia. Jika anda bercadang untuk menggunakan Django untuk membina aplikasi web anda sendiri, maka anda perlu memahami kelebihan dan kekurangan rangka kerja Django. Berikut ialah semua yang anda perlu ketahui, termasuk contoh kod khusus. Kelebihan Django: 1. Pembangunan pesat-Djang boleh membangunkan aplikasi web dengan cepat. Ia menyediakan perpustakaan yang kaya dan dalaman

Django dan Flask adalah kedua-duanya peneraju dalam rangka kerja Web Python, dan kedua-duanya mempunyai kelebihan dan senario yang boleh digunakan. Artikel ini akan menjalankan analisis perbandingan kedua-dua rangka kerja ini dan memberikan contoh kod khusus. Pengenalan Pembangunan Django ialah rangka kerja Web berciri penuh, tujuan utamanya adalah untuk membangunkan aplikasi Web yang kompleks dengan cepat. Django menyediakan banyak fungsi terbina dalam, seperti ORM (Pemetaan Hubungan Objek), borang, pengesahan, bahagian belakang pengurusan, dsb. Ciri-ciri ini membolehkan Django mengendalikan besar

Cara menaik taraf versi Django: langkah dan pertimbangan, contoh kod khusus diperlukan Pengenalan: Django ialah rangka kerja Web Python yang berkuasa yang sentiasa dikemas kini dan dinaik taraf untuk memberikan prestasi yang lebih baik dan lebih banyak ciri. Walau bagaimanapun, bagi pembangun yang menggunakan versi lama Django, menaik taraf Django mungkin menghadapi beberapa cabaran. Artikel ini akan memperkenalkan langkah dan langkah berjaga-jaga tentang cara untuk meningkatkan versi Django dan memberikan contoh kod khusus. 1. Sandarkan fail projek sebelum menaik taraf Djan

Menurut berita dari laman web ini pada 9 Januari, Tmall Elf baru-baru ini mengumumkan peningkatan perkhidmatan akses Yunyun Perkhidmatan akses Yunyun yang dinaik taraf akan bertukar daripada mod percuma kepada mod berbayar mulai 1 Januari. Tapak ini dilengkapi dengan ciri dan pengoptimuman baharu: mengoptimumkan protokol awan untuk meningkatkan kestabilan sambungan peranti; Ia mudah untuk mengikat akaun Pada masa yang sama, keizinan akaun Aplikasi pihak ketiga untuk pembangun telah ditambahkan untuk menyokong pengikatan satu klik akaun Tmall Elf telah ditambahkan sebagai tambahan kepada interaksi suara , pengguna boleh mengawal peranti dan mendapatkan maklumat melalui apl dan pembesar suara skrin, keupayaan pautan adegan pintar baharu, atribut dan peristiwa produk baharu, yang boleh dilaporkan sebagai status atau peristiwa untuk menentukan Tmall.

Django ialah rangka kerja aplikasi web yang ditulis dalam Python yang menekankan pembangunan pesat dan kaedah bersih. Walaupun Django ialah rangka kerja web, untuk menjawab soalan sama ada Django ialah front-end atau back-end, anda perlu mempunyai pemahaman yang mendalam tentang konsep front-end dan back-end. Bahagian hadapan merujuk kepada antara muka yang pengguna berinteraksi secara langsung, dan bahagian belakang merujuk kepada program bahagian pelayan Mereka berinteraksi dengan data melalui protokol HTTP. Apabila bahagian hadapan dan bahagian belakang dipisahkan, program bahagian hadapan dan bahagian belakang boleh dibangunkan secara bebas untuk melaksanakan logik perniagaan dan kesan interaktif masing-masing, dan pertukaran data.

Cara menyemak versi django: 1. Untuk menyemak melalui baris arahan, masukkan arahan "python -m django --version" dalam terminal atau tetingkap baris arahan 2. Untuk menyemak dalam persekitaran interaktif Python, masukkan "import django print(django. get_version())" code; 3. Semak fail tetapan projek Django dan cari senarai bernama INSTALLED_APPS, yang mengandungi maklumat aplikasi yang dipasang.

Django ialah bahagian belakang. Butiran: Walaupun Django terutamanya rangka kerja bahagian belakang, ia berkait rapat dengan pembangunan bahagian hadapan. Melalui ciri seperti enjin templat Django, pengurusan fail statik dan API RESTful, pembangun bahagian hadapan boleh bekerjasama dengan pembangun bahagian belakang untuk membina aplikasi web yang berkuasa dan boleh skala.
