Кеннет Рейтц – Автостопом по Python (страница 27)
Простой пользовательский интерфейс. Для того чтобы создать собственный сборщик данных, пользователь должен создать подкласс абстрактного класса Collector, а затем предоставить путь к нему с помощью конфигурационного файла. Рассмотрим пример нового определения класса Collector из класса Diamond/src/collectors/cpu/cpu.py. Когда Python ищет метод collect(), он сначала проверит на наличие CPUCollector, а затем, если оно не будет найдено, использует метод diamond.collector.Collector.collect(), что сгенерирует исключение NotImplementedError.
Код сборщика может выглядеть так:
# coding=utf-8
import diamond.collector
import psutil
class CPUCollector(diamond.collector.Collector):
····def collect(self):
········# В классе Collector содержится лишь инструкция raise(NotImplementedError)
········metric_name = "cpu.percent"
········metric_value = psutil.cpu_percent()
········self.publish(metric_name, metric_value)
Стандартное место для размещения определений сборщиков — каталог venv/share/diamond/collectors/, но вы можете хранить их по тому адресу, который укажете в свойстве collectors_path конфигурационного файла. Имя класса CPUCollector уже указано в примере конфигурационного файла. За исключением добавления спецификаций hostname или hostname_method в общие стандартные свойства (расположенные под конфигурационным файлом) или в отдельные переопределенные значения для сборщика, как показано в следующем примере, не нужно вносить другие изменения (в документации перечислены дополнительные настройки сборщиков (http://bit.ly/optional-collector-settings)):
[[CPUCollector]]
enabled = True
hostname_method = smart
Более сложен внутренний код. За кулисами сервер вызовет метод utils.load_collectors(), используя путь, указанный в collectors_path. Рассмотрим большую часть этой функции (мы сократили ее для удобства).
Примеры из стиля Diamond
В Diamond вы можете найти отличный пример использования замыкания, который демонстрирует все, о чем мы говорили в пункте «Замыкания с поздним связыванием» подраздела «Распространенные подводные камни» раздела «Стиль кода» главы 4 по поводу того, что такое поведение зачастую весьма желательно.
Пример использования замыкания (когда подводный камень вовсе не подводный камень).
Рассмотрим фрагмент кода исполняемого файла diamond, который показывает, как реализовать замыкание в Python.
Tablib
Tablib — это библиотека Python, которая преобразует данные в различные форматы, сохраняет их в объекте класса Dataset, а несколько объектов типа Datasets — в объекте класса Databook. Объекты класса Dataset хранятся в форматах JSON, YAML, DBF и CSV (файлы в этих форматах можно импортировать), наборы данных могут быть экспортированы в форматах XLSX, XLS, ODS, JSON, YAML, DBF, CSV, TSV и HTML. Библиотека Tablib выпущена Кеннетом Ритцем (Kenneth Reitz) в 2010 году, имеет интуитивный дизайн API, характерный для всех проектов Ритца.
Читаем небольшую библиотеку
Tablib — это библиотека, а не приложение, поэтому не имеет четко определенной точки входа, как в случае с HowDoI и Diamond.
Загрузите Tablib из GitHub:
$ git clone https://github.com/kennethreitz/tablib.git
$ virtualenv — p python3 venv
$ source venv/bin/activate
(venv)$ cd tablib
(venv)$ pip install — editable.
(venv)$ python test_tablib.py # Run the unit tests.
Документация Tablib (http://docs.python-tablib.org/) начинается с упоминания варианта использования, затем в ней более подробно описываются возможности библиотеки: она предоставляет объект типа Dataset, который имеет строки, столбцы и заголовки. Вы можете выполнять операции ввода/вывода из разных форматов для объекта типа Dataset. В разделе, содержащем более сложные варианты использования, говорится, что вы можете добавлять к строкам теги и создавать унаследованные столбцы, которые являются функциями других столбцов.
Tablib — это библиотека, а не исполняемый файл, как в случае с HowDoI или Diamond, поэтому вы можете открыть интерактивную сессию Python и использовать функцию help() для исследования API. Рассмотрим пример применения класса tablib.Dataset, разных форматов данных и способа работы I/O:
>>> import tablib
>>> data = tablib.Dataset()
>>> names = ('Black Knight', 'Killer Rabbit')
>>>
>>> for name in names:
… ····fname, lname = name.split()
… ····data.append((fname, lname))
…
>>> data.dict
[['Black', 'Knight'], ['Killer', 'Rabbit']]
>>>
>>> print(data.csv)
Black,Knight
Killer,Rabbit
>>> data.headers=('First name', 'Last name')
>>> print(data.yaml)
- {First name: Black, Last name: Knight}
- {First name: Killer, Last name: Rabbit}