天天看點

Tornado模闆機制分析

Tornado自帶的模闆系統非常有特色,相對django等架構來說,可以任意插入python語句,這對于前背景通吃的小團隊和個人開發者來說非常友善,而且可以友善的從Tornado架構中剝離出來單獨使用。下面簡單研究一下模闆的實作機制。

 模闆的實作集中在template.py中,之是以可以随意在模闆文本中插入python語句,是因為代碼運作時會直接将文本轉成python代碼。這是如何實作的呢?

exec self.compiled in namespace
           

exec是python的内置語句,其作用是動态執行python代碼,第一個參數可以是string,可以是打開的file object,也可以是code object。可以使用in來引入環境變量。這句代碼的意思就是在namespace所設定的環境變量中,執行self.compiled的代碼。

那麼self.compiled從何而來呢?

self.compiled = compile(self.code, self.name, "exec")
           

使用exec執行python字元串時,需要先用解釋器将其編譯為位元組代碼,為避免多次編譯導緻沒必要的時間消耗,可以預先進行編譯。

compile(source,filename,mode[,flags[,dont_inherit]])可以将字元串編譯為位元組代碼,其中source是要被編譯的字元串,filename是定義該字元串變量的檔案,如果不需要的話推薦設定為<string>,mode指定編譯類型(single指單個語句,exec指多個語句,eval指一個表達式)。

exec實際上會動态生成函數_execute(),而且将環境變量插入namespace中,這樣就可以從namespace中再取出該函數,然後執行,其結果就是以python代碼的方式完成模闆文本的解析。

execute = namespace["_execute"]
try:
     return execute()
           

那麼self.code是怎麼生成的呢?

reader = _TemplateReader(name, template_string)
self.file = _File(_parse(reader))
self.code = self._generate_python(loader, compress_whitespace)
           

詳細代碼可以參見template.py,純粹是字元串的解析,有時間再看吧。