Django(三)runserver 命令源碼分析


應用環境

  • windows7
  • pycharm2018 profession
  • python3.6
  • django2.0

我們在pycharm 啟動django項目時,常常有這么一個命令操作:

  • python manage.py runserver

 這里的意思是執行python命令,傳入的參數為 manage.py runserver。這兩個參數就會被保存到sys.argv 列表中。如下,新建一個demo.py

import sys


print('hello sys.argv')
print(type(sys.argv))
for arg in sys.argv:
    print(arg)

在terminal窗口執行 python demo.py runserver  #  循環遍歷sys.argv 輸出參數

PS:這里解釋sys.argv 是因為在manage.py中,會用到。

打開我們的manage.py文件,可以看到,這里調用的是:

  • execute_from_command_line(sys.argv)

可以看到這里傳入的就是我們執行python 命令傳入的參數(這里是manage.py runserver)。

我們進入到 execute_from_command_line 函數,可以看到的是執行

  • utility.execute()

在execute這個函數中有這么一行代碼,讀取子命令,也即是讀取sys.argv列表中第二個元素runserver,如下圖

同時,在execute函數中,我們需要重點關注的是最后這一行代碼:

  • self.fetch_command(subcommand).run_from_argv(self.argv)

這里傳入的上面的讀取的子命令sys.argv[1] 以及self.argv(這里的self.argv 是在構造函數中傳入的sys.argv)。

我們進入到 fetch_command 函數,這里最后返回的一個Command class instance 。也就是說 

  • self.fetch_command(subcommand).run_from_argv(self.argv) 

這行代碼的意思是 執行返回的實體類必然包含 run_from_argv函數。

在fetch_command中,最終調用的是

  • import_module('%s.management.commands.%s' % (app_name, name))

這里的注釋:

Given a command name and an application name, return the Command
class instance.

通過名字返回實例,這里類似net中IL編程:動態導入(動態生成程序集)【這是本篇博文的重點】。
通過:
print('%s.management.commands.%s' % (app_name, name))
我們發現動態導入的實例是:
  • django.contrib.staticfiles.management.commands.runserver

而我們的 import_module 函數最終執行的也是python標准庫 importlib下importlib._bootstrap中的gcd_import。如圖:

通過上面的分析,我們知道最終執行的是模塊:

  • django.contrib.staticfiles.management.commands.runserver

下的run_from_argv 函數。

我們打開runserver.py文件,也確是沒有找到該函數,而在其父類中找到:

從上圖看出,這個函數最終執行的是execute函數。而在execute中最終執行卻又是:

  • output = self.handle(*args, **options)

這里的handle是:

    def handle(self, *args, **options):
        """
        The actual logic of the command. Subclasses must implement
        this method.
        """
        raise NotImplementedError('subclasses of BaseCommand must provide a handle() method')

我們從注釋可以知道,這個方法需要由子類實現的,也即最后,最后,最后執行的runserver中handle函數。

分析到這里,已基本很明了,最終執行的是在本地的8000端口啟動一個socketserver監聽程序。

 

分析所得:

  • get到python如何進行動態的導入
  • sys.argv 存儲了全局中輸入參數
  • sys.moduls注冊了程序運行已經導入模塊
  • if 賦值的優雅寫法 subcommand = 'runserver'  if 1== 'condition' else 'hello'

這里一行代碼等價於這么寫:

if 1=='condition' :

    subcommand = 'runserver'

else:

  subcommand = 'hello'

這里一行代碼搞定,看起來不錯。

 

希望這篇文字可以幫助到大家。剛接觸python,若是有不對的地方,歡迎指出。謝謝。 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM