Функция _get_result() лишь оборачивает функцию requests.get() блоком try/except, чтобы можно было отловить ошибки SSL, вывести сообщение об ошибке и повторно сгенерировать исключение, дабы блок try/except верхнего уровня мог отловить его и выйти (это правило хорошего тона для любых программ).
Файл setup.py проекта HowDoI, который находится выше каталога howdoi/, — отличный пример модуля установки, поскольку в дополнение к обычной установке пакета он также устанавливает исполняемый файл (к которому вы можете обратиться при упаковке собственной утилиты командной строки). Функция установки tools.setup() использует аргументы с ключевым словом для определения всех параметров конфигурации. Та часть, которая отвечает за исполняемый файл, использует аргумент с ключевым словом entry_points.
Рис. 5.1. Прозрачные пути и прозрачные имена функций в графе вызовов проекта howdoi
Примеры из структуры HowDoI
HowDoI — это небольшая библиотека (в других разделах мы рассмотрим ее архитектуру более подробно, а здесь лишь скажем пару слов).
Мы не устанем повторять, насколько полезно разделять внутренние функции HowDoI таким образом, чтобы они делали лишь что-то одно. Существуют функции, чье единственное предназначение — оборачивание других функций в оператор try/except. (Единственная функция, имеющая оператор try/except, которая не следует этой практике, — _format_output(). Она задействует операторы try/except не для обработки исключений, а для определения языка программирования с целью подсветки синтаксиса.)
HowDoI проверяет и использует текущие системные значения, например с помощью функции urllib.request.getproxies() обрабатывается применение прокси-серверов (это подойдет для организаций вроде школ, которые имеют промежуточный сервер, фильтрующий соединение с Интернетом). Обратите внимание на этот сниппет:
XDG_CACHE_DIR = os.environ.get(
····'XDG_CACHE_HOME',
····os.path.join(os.path.expanduser('~'), '.cache')
)
Как вам узнать, что эти переменные существуют? Необходимость urllib.request.getproxies() обусловлена необязательными аргументами в requests.get(), поэтому часть этой информации доступна из сведений API о вызываемых вами библиотеках. Переменные среды зачастую нужны для определенной функциональности, поэтому, если библиотека предназначена для использования с конкретной базой данных или другим родственным приложением, в документации к этим приложениям будут перечислены актуальные переменные среды. Для систем POSIX хорошей стартовой точкой будет список стандартных переменных среды Ubuntu (https://help.ubuntu.com/community/EnvironmentVariables) или список переменных среды в спецификации POSIX (http://bit.ly/posix-env-variables), который указывает на другие важные списки.
Примеры из стиля HowDoI
HowDoI в основном следует PEP 8, но не в тех случаях, когда это вредит читаемости. Например, операторы импорта находятся в верхней части файла, но стандартная библиотека и внешние модули перемешаны. И несмотря на то что строковые константы в USER_AGENTS гораздо длиннее 80 символов, в строках нет места, где их можно было бы разбить естественным образом, поэтому они остаются целыми.
В нескольких следующих фрагментах кода показываются другие решения, связанные со стилем, о которых мы говорили в главе 4.
Имя почти каждой функции в HowDoI начинается с нижнего подчеркивания. Это показывает, что функции предназначены лишь для внутреннего использования. Для большинства из них это нужно, потому что при их прямом вызове появляется вероятность генерации необработанного исключения (этим грешат все функции, которые вызывают функцию _get_result()), до тех пор пока не будет вызвана функция howdoi(), обрабатывающая все возможные исключения.