реклама
Бургер менюБургер меню

Кеннет Рейтц – Автостопом по Python (страница 25)

18

Остальные внутренние функции (_format_output(), _is_question(), _enable_cache() и _clear_cache()) не предназначены для использования за пределами пакета. Тестирующий сценарий howdoi/test_howdoi.py вызывает только функции без префиксов, проверяя, что средство форматирования работает, и передавая аргумент командной строки для раскрашивания в функцию верхнего уровня howdoi.howdoi() вместо того, чтобы передавать код в функцию howdoi._format_output().

Разница между версиями возможных зависимостей обрабатывается перед выполнением основного кода, поэтому пользователь знает, что проблем с зависимостями не возникнет, а проверка версий не засоряет код в других местах. Это хорошо, поскольку HowDoI поставляется как инструмент командной строки и дополнительные усилия, затрачиваемые пользователями, будут означать, что им не потребуется менять свою среду Python, чтобы установить инструмент. Рассмотрим фрагмент кода, в котором решается эта проблема:

try:

····from urllib.parse import quote as url_quote

except ImportError:

····from urllib import quote as url_quote

try:

····from urllib import getproxies

except ImportError:

····from urllib.request import getproxies

В следующем сниппете разница подходов к обработке Unicode в Python 2 и Python 3 нивелируется всего за семь строк путем создания функции u(x), которая либо эмулирует Python 3, либо не делает ничего. Кроме того, он следует новым принципам цитирования Stack Overflow (http://meta.stackexchange.com/questions/271080), приводя оригинальный исходный код:

# Разрешаем разницу обработки Unicode между Python 2 и 3

# http://stackoverflow.com/a/66 33040/3 05414

if sys.version < '3':

····import codecs

····def u(x):

········return codecs.unicode_escape_decode(x)[0]

else:

····def u(x):

········return x Питонские решения (красивое лучше, чем уродливое)

В следующем фрагменте кода из файла howdoi.py показываются продуманные, питонские решения. Функция get_link_at_pos() возвращает значение False, если результаты не найдены, или определяет ссылки на вопросы, касающиеся Stack Overflow, и возвращает ту из них, которая находится на желаемой позиции (либо последнюю, если ссылок недостаточно).

Функция _is_question() определяется в отдельной строке, что указывает четкое значение непонятному в противном случае поиску с использованием регулярных выражений.

Списковое включение читается как предложение благодаря отдельному определению функции _is_question() и информативным именам переменных.

Раннее использование оператора возврата упрощает код.

Дополнительный шаг, который тратится на присваивание значения переменной link, здесь…

…и здесь вместо использования двух отдельных операторов возврата, не имеющих именованных переменных, подчеркивает предназначение функции get_link_at_pos() с помощью прозрачных имен переменных. Код самозадокументирован.

Единый оператор возврата, находящийся на высшем уровне отступов, явно показывает, что все пути по коду завершатся либо сразу (поскольку ссылки не найдены), либо в конце функции, вернув ссылку. Работает наше правило: мы можем прочесть первую и последнюю строки этой функции и понять, что она делает. (Получив несколько ссылок и позицию, функция get_link_at_pos() возвращает одну ссылку, которая находится на заданной позиции.)

Diamond

Diamond — это демон (приложение, постоянно работающее как фоновый процесс), который собирает метрики системы и публикует их в программах вроде MySQL, Graphite (http://graphite.readthedocs.org/) (платформа с открытым исходным кодом, созданная компанией Orbitz в 2008 году, которая сохраняет, получает и по возможности строит графики на основе временных рядов) и др. У нас есть возможность взглянуть на хорошую структуру пакетов, поскольку Diamond состоит из нескольких файлов и гораздо крупнее HowDoI.

Читаем более крупное приложение

Diamond также является приложением командной строки, поэтому, как и в случае с HowDoI, существуют четкая стартовая точка и четкие пути выполнения, однако теперь поддерживающий код находится в нескольких файлах.

Загрузите Diamond с GitHub (в документации говорится, что программа работает только в ОС CentOS или Ubuntu, но код, находящийся в ее файле setup.py, позволяет ей запускаться на всех платформах. Однако отдельные команды, которые стандартные сборщики используют для наблюдения за памятью, дисковым пространством и другими системными метриками, отсутствуют в Windows). На момент написания этой книги программа все еще использует Python 2.7:

$ git clone https://github.com/python-diamond/Diamond.git

$ virtualenv — p python2 venv # Она все еще несовместима с Python 3…

$ source venv/bin/activate

(venv)$ cd Diamond/

(venv)$ pip install — editable.

(venv)$ pip install mock docker-py # Эта зависимость нужна для тестирования.

(venv)$ pip install mock # Эта зависимость также нужна для тестирования.

(venv)$ python test.py # Запускаем юнит-тесты.

Как и в случае с библиотекой HowDoI, сценарий установки Diamond добавляет исполняемые файлы diamond и diamond-setup в каталог venv/bin/. В этот раз они не генерируются автоматически, а являются заранее написанными сценариями и лежат в каталоге Diamond/bin/. В документации говорится, что файл diamond запускает сервер, а diamond-setup — необязательный инструмент, который позволяет пользователям интерактивно изменять настройки сборщика в конфигурационном файле.

Существует множество дополнительных каталогов, пакет diamond находится внутри каталога Diamond/src. Мы взглянем на файлы из каталогов Diamond/src (в которых содержится основной код), Diamond/bin (хранится исполняемый файл diamond) и Diamond/conf (содержится пример конфигурационного файла). Остальные каталоги и файлы могут представлять интерес для тех, кто хочет распространять подобные приложения (в рамках этой книги мы их опустим).

Для начала можно попытаться понять идею проекта, взглянув на онлайн-документацию (http://diamond.readthedocs.io/). Цель Diamond — упрощение сборки системных метрик для кластеров машин. Появилась в 2011 году благодаря компании BrightCove, Inc., на сегодняшний день в ее базу кода внесли вклад более 200 человек.

После описания истории и предназначения в документации говорится, как установить и запустить демон: вам нужно лишь модифицировать предложенный файл конфигурации (у нас он находится по адресу conf/diamond.conf.example), поместить в стандартное место (/etc/diamond/diamond.conf) или по пути, который вы укажете в командной строке, — и вы готовы приступить к работе. Кроме того, на вики-странице проекта Diamond (https://github.com/BrightcoveOS/Diamond/wiki/Configuration) вы можете найти полезный раздел о конфигурации.

Из командной строки мы можем вывести на экран руководство по использованию с помощью команды diamond — help:

(venv)$ diamond — help

Usage: diamond [options]

Options:

··-h, — help ···········show this help message and exit

··-c CONFIGFILE, — configfile=CONFIGFILE

························config file

··-f, — foreground ·····run in foreground

··-l, — log-stdout ·····log to stdout

··-p PIDFILE, — pidfile=PIDFILE

························pid file

··-r COLLECTOR, — run=COLLECTOR

························run a given collector once and exit

··-v, — version ········display the version and exit

··-skip-pidfile ·······Skip creating PID file

··-u USER, — user=USER ·Change to specified unprivileged user

··-g GROUP, — group=GROUP

························Change to specified unprivileged group

··-skip-change-user ···Skip changing to an unprivileged user

··-skip-fork ··········Skip forking (damonizing) process

Из него мы узнаем, что демон использует файл конфигурации; по умолчанию работает в фоновом режиме; имеет возможность журналирования. Вы можете указать файл PID (process ID, «идентификатор процесса»), протестировать сборщики, можете изменить пользователя и группу процесса. По умолчанию он демонизирует (создаст копию) процесс[56].