Openstack : 16、Openstack-開發基礎 stevedore學習_openstack

來源:互聯網
上載者:User

以下內容來自:http://blog.csdn.net/gqtcgq/article/details/49620279


  stevedore是用來實現動態載入代碼的開源模組。它是在OpenStack中用來載入外掛程式的公用模組。可以獨立於OpenStack而安裝使用:https://pypi.Python.org/pypi/stevedore/

 

         stevedore使用setuptools的entry points來定義並載入外掛程式。entry point引用的是定義在模組中的對象,比如類、函數、執行個體等,只要在import模組時能夠被建立的對象都可以。

 

一:外掛程式的名字和命名空間

         一般來講,entry point的名字是公開的,使用者可見的,經常出現在設定檔中。而命名空間,也就是entry point組名卻是一種實現細節,一般是面向開發人員而非終端使用者的。可以用Python的包名作為entry  point命名空間,以保證唯一性,但這不是必須的。

         entry points的主要特徵就是,它可以是獨立註冊的,也就是說外掛程式的開發和安裝可以完全獨立於使用它的應用,只要開發人員和使用者在命名空間和API上達成一致即可。

         命名空間被用來搜尋entry points。entry points的名字在給定的發布包中必須是唯一的,但在一個命名空間中可以不唯一。也就是說,同一個發布包內不允許出現同名的entry point,但是如果是兩個獨立的發布包,卻可以使用完全相同的entrypoint組名和entry point名來註冊外掛程式。

 

二:外掛程式的使用方式

         在stevedore中,有三種使用外掛程式的方式:Drivers、Hooks、Extensions

1:Drivers      

         一個名字對應一個entry point。使用時根據外掛程式的命名空間和名字,定位到單獨的外掛程式:

         2:Hooks,一個名字對應多個entry point。允許同一個命名空間中的外掛程式具有相同的名字,根據給定的命名空間和名字,載入該名字對應的多個外掛程式。

 

         3:Extensions,多個名字,多個entry point。給定命名空間,載入該命名空間中所有的外掛程式,當然也允許同一個命名空間中的外掛程式具有相同的名字。

三:定義並註冊外掛程式

         在經過了大量的實驗和總結教訓之後,發現定義API最簡單的方式是遵循下面的步驟:

         a:使用abc模組,建立一個抽象基類來定義外掛程式API的行為;雖然開發人員無需繼承一個基類,但是這種方式自有它的好處;

         b:通過繼承基類並實現必要的方法來建立外掛程式

         c:為每個API定義一個命名空間。可以將應用或者庫的名字,以及API的名字結合起來,這種方式通俗易懂,如 “cliff.formatters”或“ceilometer.pollsters.compute”。

 

         本節例子中建立的外掛程式,用來對資料進行格式化輸出,每個格式化方法接受一個字典作為輸入,然後按照一定的規則產生要輸出的字串。格式化類可以有一個最大輸出寬度的參數。

 

         1:首先定義一個基類,其中的API需要由外掛程式來實現

[python]  view plain  copy # example/pluginbase.py      import abc   import six       @six.add_metaclass(abc.ABCMeta)   class FormatterBase(object):       """Base class for example plugin used in the tutorial."""          def __init__(self, max_width=60):           self.max_width = max_width         @abc.abstractmethod       def format(self, data):           """Format the data and return unicode text.            :param data: A dictionary with string keys and simple types as                       values.          :type data: dict(str:?)          :returns: Iterable producing the formatted text.          """  

          2:定義外掛程式1

         開始定義具體的外掛程式類,這些類需要實現format方法。下面是一個簡單的外掛程式,它產生的輸出都在一行上。

[python]  view plain  copy # example/simple.py      import pluginbase      class Simple(pluginbase.FormatterBase):       """A very basic formatter.      """          def format(self, data):           """Format the data and return unicode text.            :param data: A dictionary with string keys and simple types as                       values.          :type data: dict(str:?)          """           for name, value in sorted(data.items()):               line = '{name} = {value}\n'.format(                   name=name,                   value=value,               )               yield line  

          3:註冊外掛程式1

         本例中,使用” stevedoretest.formatter”作entry points的命名空間,也就是entry points組名,源碼樹如下:

[plain]  view plain  copy setup.py   example/       __init__.py       pluginbase.py       simple.py  

         該發布包的setup.py內容如下:

[python]  view plain  copy from setuptools import setup, find_packages      setup(       name='stevedoretest1',       version='1.0',          packages=find_packages(),          entry_points={           'stevedoretest.formatter': [               'simple = example.simple:Simple',               'plain = example.simple:Simple',           ],       },   )  

         每個entry point都以” name = module:importable ”的形式進行註冊,name就是外掛程式的名字,module就是python模組,importable就是模組中可引用的對象。

         這裡註冊了兩個外掛程式,simple和plain,這兩個外掛程式所引用的Python對象是一樣的,都是example.simple:Simple類,因此plain只是simple的別名而已。

        

         定義好setup.py之後,運行python setup.py install即可安裝該發布包。安裝成功後,在該發布的egg目錄中存在檔案entry_points.txt,其內容如下:

[plain]  view plain  copy [stevedoretest.formatter]   plain = example.simple:Simple   simple = example.simple:Simple  

         運行時,pkg_resources在所有已安裝包的entry_points.txt中尋找外掛程式,因此不要手動編輯該檔案。

 

          4:定義外掛程式2

         使用entry points建立外掛程式的好處之一就是,可以為一個應用獨立的開發不同的外掛程式。因此可以在另外一個發布包中定義第二個外掛程式:

[python]  view plain  copy #example2/fields.py   import textwrap      from example import pluginbase         class FieldList(pluginbase.FormatterBase):       """Format values as a reStructuredText field list.        For example::          : name1 : value        : name2 : value        : name3 : a long value            will be wrapped with            a hanging indent      """          def format(self, data):           """Format the data and return unicode text.            :param data: A dictionary with string keys and simple types as                       values.          :type data: dict(str:?)          """           for name, value in sorted(data.items()):               full_text = ': {name} : {value}'.format(                   name=name,                   value=value,               )               wrapped_text = textwrap.fill(                   full_text,                   initial_indent='',                   subsequent_indent='    ',                   width=self.max_width,               )               yield wrapped_text + '\n'  

          5:註冊外掛程式2

         外掛程式2的源碼樹如下:

[plain]  view plain  copy setup.py   example2/       __init__.py       fields.py  

         在setup.py中,同樣要使用”stevedoretest.formatter”作為entry points組名,該發布包的setup.py內容如下:

[python]  view plain  copy from setuptools import setup, find_packages      setup(       name='stevedoretest2',       version='1.0',          packages=find_packages(),          entry_points={           'stevedoretest.formatter': [               'fields = example2.fields:FieldList'           ],       },   )  

         這裡註冊了外掛程式fields,它引用的是example2.fields:FieldList類。定義好setup.py之後,運行python setup.py install即可安裝該發布包。在該發布的entry_points.txt檔案內容如下:

[plain]  view plain  copy [stevedoretest.formatter]   fields = example2.fields:FieldList  

四:載入外掛程式

         1:Drivers載入

         最常見的使用外掛程式的方式是作為單獨的驅動來使用,這種情境中,可以有多種外掛程式,但只需要載入和調用其中的一個,這種情況下,可以使用stevedore的DriverManager 類。下面就是一個使用該類的例子:

[python]  view plain  copy from __future__ import print_function      import argparse      from stevedore import driver         if __name__ == '__main__':       parser = argparse.ArgumentParser()       parser.add_argument(           'format',           nargs='?',           default='simple',           help='the output format',       )       parser.add_argument(           '--width',           default=60,           type=int,           help='maximum output width for text',       )       parsed_args = parser.parse_args()          data = {           'a': 'A',           'b': 'B',           'long': 'word ' * 80,       }          mgr = driver.DriverManager(           namespace='stevedoretest.formatter',           name=parsed_args.format,           invoke_on_load=True,           invoke_args=(parsed_args.width,),       )       for chunk in mgr.driver.format(data):           print(chunk, end='')  

         其中的parser主要用來解析命令列參數的,該指令碼接受三個參數,一個是format,也就是要使用的外掛程式名字,這裡預設是simple;另一個參數是--width,是外掛程式方法可能會用到的參數,這裡預設是60,該指令碼還可以通過--help參數列印協助資訊:

[python]  view plain  copy # python load_as_driver.py --help   usage: load_as_driver.py [-h] [--width WIDTH] [format]      positional arguments:     format         the output format      optional arguments:     -h, --help     show this help message and exit     --width WIDTH  maximum output width for text  

         在該指令碼中,driver.DriverManager以外掛程式的命名空間以及外掛程式名來尋找外掛程式,也就是entry points組名和entry points本身的名字。也就是希望通過組名和entry point本身的名字來唯一定位一個外掛程式,但是因為相同的entry points組中可以有同名的entry point,所以,對於DriverManager來說,如果通過entry points組名和entry points本身的名字找到了多個註冊的外掛程式,則會報錯。比如本例中,如果在”stevedoretest.formatter”中,有多個發布模組註冊了名為”simiple”的entry point,則執行該指令碼時就會報錯:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.