Python 模板庫 Mako 的用法

2021-03-02 Python開發者

(點擊上方藍字,快速關注我們)

來源:for-in

my.oschina.net/liuyuantao/blog/747167

如有好文章投稿,請點擊 → 這裡了解詳情

Mako是一個高性能的Python模板庫,它的語法和API借鑑了很多其他的模板庫,如Django、Jinja2等等。

基本用法

創建模板並渲染它的最基本的方法是使用 Template 類:

from mako.template import Template

t = Template('hello world!')

print t.render()

傳給 Template 的文本參數被編譯為一個Python模塊。模塊包含一個 render_body() 函數,它產生模板的輸出。調用 render() 方法時,Mako建立了一個模板的運行環境,並調用 render_body() 函數,把輸出保存到緩衝,返回它的字符串內容。

render_body() 函數中可以訪問一個變量集。可以向 render() 方法發送額外的關鍵詞參數來指定這些變量:

from mako.template import Template

t = Template('hello, ${name}!')

print t.render(name='yeolar')

ender() 方法使Mako創建一個 Context 對象,它存儲模板可以訪問的所有變量和一個用來保存輸出的緩衝。也可以自己創建 Context ,用 render_context() 方法使模板用它來渲染:

from mako.template import Template

from mako.runtime import Context

from StringIO import StringIO

t = Template('hello, ${name}!')

buf = StringIO()

c = Context(buf, name='yeolar')

t.render_context(c)

print buf.getValue()

使用文件模板

Template 也可以從文件加載模板,使用 filename 參數:

from mako.template import Template

t = Template(filename='/docs/tpl.txt')

print t.render()

為了提高性能,從文件加載的 Template 還可以在文件系統中將生成的模塊緩存為一般的Python模塊文件(.py文件),這通過添加 module_directory 參數實現:

from mako.template import Template

t = Template(filename='/docs/tpl.txt', module_directory='/tmp/mako_modules')

print t.render()

上面的代碼渲染後,會創建一個/tmp/mako_modules/docs/tpl.txt.py文件,其中包含模塊的原始碼。下次同樣參數的 Template 創建時,自動重用這個模塊文件。

使用TemplateLookup

到現在的例子都是有關單個 Template 對象的用法。如果模板中的代碼要定位其他模板資源,需要某種使用URI來找到它們的方法。這種需求是由 TemplateLookup 類來達到的。這個類通過傳入一個模板查找目錄的列表來構造,然後作為關鍵詞參數傳給 Template 對象:

from mako.template import Template

from mako.lookup import TemplateLookup

lookup = TemplateLookup(directories=['/docs'])

t = Template('<%include file="header.txt" /> hello word!', lookup=lookup)

上面創建的模板中包含文件header.txt。為了查找header.txt,傳了一個 TemplateLookup 對象給它。

通常,應用會以文本文件形式在文件系統上存儲大部分或全部的模板。一個真正的應用會直接從 TemplateLookup 取得它的模板,使用 get_template() 方法,它接受需要的模板的URI作為參數:

from mako.template import Template

from mako.lookup import TemplateLookup

lookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules')

def serve_template(t_name, **kwargs):

    t = lookup.get_template(t_name)

    print t.render(**kwargs)

面的例子中我們創建了一個 TemplateLookup ,它從/docs目錄中查找模板,並把所有的模塊文件存儲到/tmp/mako_modules目錄中。通過將傳入的URI附加到每個查找目錄來定位模 板,如傳遞/etc/beans/info.txt,將查找文件/docs/etc/beans/info.txt,如果沒找到將拋出 TopLevelNotFound 異常。

當定位到模板的時候,傳給 get_template() 調用的URI也會作為 Template 的 uri 屬性。 Template 使用這個URI來得到模塊文件的名字,因此上面的例子中對/etc/beans/info.txt會創建模塊文件/tmp/mako_modules /etc/beans/info.txt.py。

設置收集的大小

TemplateLookup 還滿足將內存中緩存的模板總數設為一個固定的值。默認情況 TemplateLookup 大小是不限的。可以用 collection_size 參數指定一個固定值:

lookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules', collection_size=500)

 

上面的 lookup 將模板加載到內存中的上限是500個。之後,它將使用LRU策略來清理替換模板。

設置文件系統檢查

TemplateLookup 的另一個重要標誌是 filesystem_checks 。默認為 True ,每次 get_template() 方法返回一個模板,會比較原始模板文件的修改時間和模板的最近加載時間,如果文件更新,就重新加載和編譯模板。在生產系統中,將 filesystem_checks 設為 False 能獲得一些性能的提升。

使用Unicode和編碼

Template 和 TemplateLookup 可以設置 output_encoding 和 encoding_errors 參數來將輸出編碼為Python支持的編碼格式:

from mako.template import Template

from mako.lookup import TemplateLookup

lookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')

t = lookup.get_template('foo.txt')

print t.render()

使用Python 3時,如果設置了 output_encoding , render() 方法將返回一個 bytes 對象,否則返回 string 。

render_unicode() 方法返回模板輸出為Python unicode 對象,Python 3為 string :

print t.render_unicode()

上面的方法沒有輸出編碼的參數,可以自行編碼:

print t.render_unicode().encode('utf-8', 'replace')

 

注意Mako中模板的底層輸出流是Python Unicode對象。

處理異常

模板異常可能發生在兩個地方。一個是當你查找、解析和編譯模板的時候,一個是運行模板的時候。模板運行中發生的異常會正常在產生問題的Python代碼處 拋出。Mako有自己的一組異常類,它們主要用於模板構造的查找和編譯階段。Mako提供了一些庫例程用來對異常棧提供Mako的信息,並將異常輸出為文 本或HTML格式。Python文件名、行號和代碼片段會被轉換為Mako模板文件名、行號和代碼片段。Mako模板模塊的行會被轉換為原始的模板文件對 應行。

text_error_template() 和 html_error_template() 函數用于格式化異常跟蹤。它們使用 sys.exc_info() 來得到最近拋出的異常。這些處理器的用法像下面這樣:

from mako import exceptions

try:

    t = lookup.get_template(uri)

    print t.render()

except:

    print exceptions.text_error_template().render()

或者渲染為HTML:

from mako import exceptions

try:

    t = lookup.get_template(uri)

    print t.render()

except:

    print exceptions.html_error_template().render()

html_error_template() 模板接受兩個選項:指定 full=False 只渲染HTML的一節,指定 css=False 關閉默認的樣式表。如:

print exceptions.html_error_template().render(full=False)

HTML渲染函數也可以用 format_exceptions 標誌加到 Template 中。這種情況下,模板在渲染階段的任何異常在輸出中的結果都會替換為 html_error_template() 的輸出:

t = Template(filename='/foo/bar', format_exceptions=True)

 

print t.render()

注意上面模板的編譯階段發生在構造 Template 時,沒有定義輸出流。因此查找、解析、編譯階段發生的異常正常情況下不會被處理,而是傳播下去。渲染前的追溯不包括Mako形式的行,這意味著渲染前和渲 染中發生的異常會用不同的方式處理,因此 try/except 可能更常用。

錯誤模板函數使用的底層對象是 RichTraceback 對象。這個對象也可以直接用來提供自定義的錯誤視圖。下面是一個用法的樣例:

from mako.exceptions import RichTraceback

try:

    t = lookup.get_template(uri)

    print t.render()

except:

    traceback = RichTraceback()

    for (filename, lineno, function, line) in traceback.traceback:

        print 'File %s, line %s, in %s' % (filename, lineno, function)

        print line, '\n'

    print '%s: %s' % (str(traceback.error.__class__.__name__), traceback.error)

集成Mako

在Django中集成Mako

通過Django的中間件可以集成Mako。首先需要安裝django-mako模塊。

在Django項目的settings.py文件中,修改 MIDDLEWARE_CLASSES ,添加 djangomako.middleware.MakoMiddleware 。使用 render_to_response() 函數即可使用:

在Tornado中集成Mako

在Tornado中可以直接使用Mako,下面是一個使用示例:

import tornado.web

import mako.lookup

import mako.template

LOOK_UP = mako.lookup.TemplateLookup(

        directories=[TEMPLATE_PATH], module_directory='/tmp/mako',

        output_encoding='utf-8', encoding_errors='replace')

class BaseHandler(tornado.web.RequestHandler):

    def initialize(self, lookup=LOOK_UP):

        '''Set template lookup object, Defalut is LOOK_UP'''

        self._lookup = lookup

    def render_string(self, filename, **kwargs):

        '''Override render_string to use mako template.

        Like tornado render_string method, this method

        also pass request handler environment to template engine.

        '''

        try:

            template = self._lookup.get_template(filename)

            env_kwargs = dict(

                handler = self,

                request = self.request,

                current_user = self.current_user,

                locale = self.locale,

                _ = self.locale.translate,

                static_url = self.static_url,

                xsrf_form_html = self.xsrf_form_html,

                reverse_url = self.application.reverse_url,

                )

            env_kwargs.update(kwargs)

            return template.render(**env_kwargs)

        except:

            # exception handler

            pass

    def render(self, filename, **kwargs):

        self.finish(self.render_string(filename, **kwargs))

看完本文有收穫?請轉發分享給更多人

關注「Python開發者」,提升Python技能

相關焦點

  • 3個既簡單又強大的Python Web 框架
    基於Werkzeug WSGI工具箱和Jinja2 模板引擎。 Flask使用BSD授權。 Flask也被稱為「microframework」,因為它使用簡單的核心,用extension增加其他功能。Flask沒有默認使用的資料庫、窗體驗證工具。然而,Flask保留了擴增的彈性,可以用Flask-extension加入這些功能:ORM、窗體驗證工具、文件上傳、各種開放式身份驗證技術。
  • Python爬蟲利器一之Requests庫的用法
    註:Python 版本依然基於 2.7前言之前我們用了 urllib 庫,這個作為入門的工具還是不錯的,對了解一些爬蟲的基本理念,掌握爬蟲爬取的流程有所幫助。入門之後,我們就需要學習一些更加高級的內容和工具來方便我們的爬取。那麼這一節來簡單介紹一下 requests 庫的基本用法。
  • Python常用庫大全
    ptpython – 高級交互式Python解析器, 構建於python-prompt-toolkit 之上。 python-magic- 文件類型檢測的第三方庫 libmagic 的 Python 接口。
  • Python爬蟲--Requests 庫用法大全
    昨晚分享了Python爬蟲的基本知識,本文分享一下爬蟲裡面請求相關的內容:Requests 用法。
  • 每個python人都離不開的12個python庫
    如果說python能取得今天的成就,一方面是它簡介的語法,更重要的一方面就是它豐富的第三方庫,可以毫不誇張的說,只要你能想到的任何一個功能模塊,都有對應的python庫,可以說正是因為有了豐富的python庫,python才發展得如此迅速,下面我們來看看python人最常用的20個python
  • Python中time庫的使用
    time庫是python中處理時間的標準庫。時間獲取time.time(): 獲取當前時間戳,即計算機內部時間值,浮點數time.ctime(): 獲取當前時間並以一種易讀的形式表示,返回字符串time.gmtime(): 獲取當前時間,表示為計算機可以處理的時間格式時間格式化將計算機內部表達的年月日時分秒等與時間有關的信息,用一種變量的形式合理組合併且合理輸出,通過控制表達輸出格式,展示模板由特定的格式化控制符組成
  • 推薦一些能提高生產力的 Python 庫
    一些回答直接把 awesome-python 貼過來,點讚非常多,當然多歸多,但是裡面很多都是些過期的或者其實沒太有什麼價值的庫,反而會增加了挑選庫的成本。我大體上把一些回答過了一遍,另外結合自己平時了解的內容,稍微對一些基礎生產力庫做了簡單的梳理,在這裡分享給大家。
  • Helm 模板使用方法(一)
    Helm Chart 模板使用的是 Go語言模板編寫而成,並添加了 Sprig庫中的50多個附件模板函數以及一些其他特殊的函。需要注意的是 kubernetes資源對象的 labels 和 name 定義被限制 63個字符,所以需要注意名稱的定義。
  • Python 用xlwings庫處理Excel
    xlwing庫在網上查看了一些python處理excel庫資料,參考相關內容《Python讀寫Excel文件第三方庫匯總,你想要的都在這兒
  • Python字符串及Time庫介紹
    關於Time庫有Time庫的介紹,時間獲取,時間格式化,程序計時應用。簡單介紹Time庫:Time庫作為python中處理時間的標準庫,當然,Python中也有若干個處理時間的庫,但Time庫是最基本的一個。
  • Python爬蟲之基本庫的使用
    但是沒關係,python為我們提供了功能齊全的類庫來幫助我們完成這些請求。最基礎的HTTP庫有urllib、requests、treq等。以urllib為例,有了它,我們只需要關心請求的連接是什麼。需要傳的參數是什麼,以及如何設置可選的請求頭就好了,不用深入到底層去了解它到底是怎樣傳輸和通信的。有了它,兩行代碼就可以完成一個請求和相應的處理過程,得到網頁內容,是不是感覺方便極了?
  • 詳解Python中的import的用法
    import語句用來導入其他python文件(稱為模塊module),使用該模塊裡定義的類、方法或者變量,從而達到代碼復用的目的。為了方便說明,我們用實例來說明import的用法,讀者朋友可以跟著嘗試(嘗試時建議使用python3,python2和python3在import的表現有差異,之後會提到)。
  • 10-python爬蟲之lxml庫
    lxml 是一種使用 Python 編寫的庫,可以迅速、靈活地處理 XML ,支持 XPath (XML Path Language)lxml
  • 慢步python,說說import,引用功能代碼(功能庫、py文件代碼)
    今天慢步休息,繼續學習python語言。其實慢步已經將基礎和必要的python語言知識點寫了。今天想說說importimport是python語言的保留字,它能實現引用當前程序之外已有的功能代碼。python語言像積木,你可以根據你想要的功能,編寫一系列的代碼。比如筆者之前編寫的《word文檔標題置換》。
  • Python擴展庫安裝與常見問題解決完整指南
    截至2021年1月,pypi已經收錄了超過28萬個擴展庫項目,涉及很多領域的應用,例如jieba(用於中文分詞)、moviepy(用於編輯視頻文件)、xlrd(用於讀取Excel 2003之前版本文件)、xlwt(用於寫入Excel 2003之前版本文件)、openpyxl(用於讀寫Excel2007及更高版本文件)、python-docx(用於讀寫Word 2007及更新版本文件)、python-pptx
  • Python數據分析之NumPy庫
    NumPy庫簡介NumPy庫使用Python進行科學計算,尤其是數據分析時,所用到的一個基礎庫。它是大量Python數學和科學計算包的基礎,比如我們後面會講到的pandas庫就用到了NumPy。pandas庫專門用於數據分析,充分借鑑了Python標準庫NumPy的相關概念。
  • python推薦 | 面向地學領域的Python庫匯總
    數據處理•NetCDF格式 : netCDF4-python,h5py,h5netcdf,xarray等。除了上述簡單的數據處理庫之外,python還提供了NCO和CDO工具的封裝,pynco和cdo,提供了更多的便捷操作。•Grib格式:xarray,Iris,pygrib等,有些僅支持類Unix系統。
  • 5個奇妙的Python庫
    點擊上方「深度學習愛好者」,選擇加"星標"或「置頂」重磅乾貨,第一時間送達引言Python是一個非常神奇語言,無論我們要做什麼任務,python都有其解決方案,無論它與機器學習,數據可視化Python為各種簡單和困難的任務提供了大量的庫。大多數人都知道類似Pandas,Numpy,Matplotlib,Seaborn,OpenCV,Plotly這樣的庫,還有很多其他在機器學習中使用的庫。但是對於很多小的需求,python同樣有很多奇妙的庫。本文將分享一些在項目中遇到的一些庫,這些庫具有很高的可移植性,對於每個庫我都將用一個代碼段來介紹。
  • python機器學習:常用庫的介紹及安裝
    1、為了學習方便,建議大家安裝Anaconda(由於平臺不讓給出網站連結,所以具體連結直接百度搜一下就可以得到),為什麼建議使用這個軟體呢,因為安裝了這個軟體後本身就自帶了IPython、Numpy、pandas,scikit-learn等庫,不用你去在一步一步的去安裝其他的庫;並且該軟體兼容性不錯,可以在Mac OS, windows和linux上運行,一勞永逸,非常方便。
  • 10個Python程序必備庫,介紹給大家
    Python是 一個很好入門的程式語言,現在也很火只要是開發人員都應該多多少少會去學習下python怎麼使用,它之所有很火除了語法很自由以為,還有很大量的可以使用的python庫,包括本地庫和第三方庫。然而,由於python庫太多了,因此有些很好用的庫沒有受到太多的關注也就不足為奇了。另外,專門在一個領域工作的小夥伴並不總是知道其他領域的庫對有他有什麼好處。