Это обычный рабочий день для «Удиви-кота».
Монти Пайтон
Python развивается, чтобы идти в ногу с меняющимся техническим миром. В этой главе рассматриваются специфические возможности этого языка, относящиеся к описанным в предыдущей главе вопросам, а также некоторые дополнительные:
• инструменты;
• API и сервисы;
• переменные и подсказки типов;
• структуры данных;
• веб-фреймворки.
В каждом языке программирования есть следующие элементы:
• основной язык и встроенные стандартные пакеты;
• способы добавления сторонних пакетов;
• рекомендуемые сторонние пакеты;
• среда инструментов разработки.
В следующих разделах перечислены инструменты Python, необходимые или рекомендуемые для работы с книгой.
Со временем они могут измениться! Средства упаковки и разработки Python — это движущиеся цели, и время от времени появляются более совершенные решения.
Вы должны уметь написать и запустить программу на Python, подобную приведенной в примере 2.1.
Пример 2.1. Программа на языке Python: this.py
def paid_promotion():
print("(that calls this function!)")
print("This is the program")
paid_promotion()
print("that goes like this.")
Чтобы запустить эту программу из командной строки в текстовом окне или терминале, я буду использовать подсказку $ (ваша система умоляет вас набрать что-нибудь поскорее). То, что вы вводите после подсказки, отображается полужирным шрифтом. Если вы сохранили пример 2.1 в файл this.py, его можно запустить, как показано в примере 2.2.
Пример 2.2. Тестирование файла this.py
$ python this.py
This is the program
(that calls this function!)
that goes like this.
В некоторых примерах кода используется интерактивный интерпретатор Python. Доступ к нему можно получить, просто набрав слово python:
$ python
Python 3.9.1 (v3.9.1:1e5d33e9b9, Dec 7 2020, 12:10:52)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
Первые несколько строк зависят от вашей операционной системы и версии Python. Символы >>> означают предложение ввода команд. Удобная дополнительная функция интерактивного интерпретатора заключается в том, что он выводит значение переменной, если вы введете ее имя:
>>> wrong_answer = 43
>>> wrong_answer
43
Это работает и для выражений:
>>> wrong_answer = 43
>>> wrong_answer - 3
40
Если вы совсем недавно познакомились с Python или хотите получить краткий обзор, прочтите следующие несколько подразделов.
Вам понадобится как минимум Python 3.7. У него имеются такие возможности, как подсказки типов и модуль asyncio, которые являются основными требованиями FastAPI. Я же рекомендую использовать по крайней мере Python 3.9 с более длительным сроком поддержки. Стандартный источник для получения Python — Python Software Foundation (https://www.python.org).
Вам нужно будет загрузить сторонние пакеты Python и безопасно установить их на свой компьютер. Классическим инструментом для этого служит система pip (https://pip.pypa.io).
Но как загрузить этот загрузчик? Если вы установили Python от Python Software Foundation, у вас уже должен быть pip. Если нет, следуйте инструкциям на сайте pip, чтобы получить его. На протяжении всей этой книги, когда я буду представлять новый пакет Python, стану указывать и команду pip для его загрузки.
Вы можете многое сделать с помощью старого доброго pip, но, скорее всего, вам захочется также использовать виртуальные среды и рассмотреть альтернативные инструменты, такие как Poetry.
Pip загрузит и установит пакеты, но куда он должен их поместить? Хотя стандартный Python и входящие в него библиотеки обычно устанавливаются в стандартное место в вашей операционной системе, вы не сможете (и, скорее всего, не должны) ничего там изменить. Pip использует каталог по умолчанию, отличный от системного, поэтому установка не попадет на стандартные файлы Python в вашей системе. Это можно изменить. Подробности для своей операционной системы смотрите на сайте pip.
Часто приходится работать с несколькими версиями Python или устанавливать версии для конкретного проекта, поэтому вам точно будет известно, какие пакеты находятся в системе. Для этого Python поддерживает виртуальные среды. Это просто каталоги (папки в не-Unix-мире), в которые pip записывает загруженные пакеты. Когда вы активируете виртуальную среду, ваша оболочка (интерпретатор основных системных команд) при загрузке модулей Python в первую очередь обращается к ней. Для этого используется программа venv (https://oreil.ly/9kv5T), которая входит в стандартный пакет установки Python начиная с версии 3.4.
Создадим виртуальную среду под названием venv1. Вы можете запустить модуль venv как отдельную программу:
$ venv venv1
или в качестве модуля Python:
$ python -m venv venv1
Чтобы сделать его своей текущей средой Python, выполните эту команду оболочки (в Linux или Mac, для Windows и других ОС смотрите документацию venv):
$ source venv1/bin/activate
Теперь каждый раз, когда вы запускаете pip install, пакеты будут устанавливаться в среду venv1. Когда запускаете программы Python, именно там находятся ваш интерпретатор Python и модули.
Чтобы отключить виртуальную среду, нажмите сочетание клавиш Control+D (для Linux или Mac) или введите команду deactivate (для Windows).
Можно создать альтернативные среды разработки, например venv2, и деактивировать/активировать их, чтобы переходить от одной к другой (хотя я надеюсь, что у вас лучше фантазия в плане названий, чем у меня).
Сочетание pip и venv настолько распространено, что люди начали комбинировать их, чтобы сократить этапы работы и избежать source-премудростей оболочки. Одним из таких пакетов стал Pipenv (https://pipenv.pypa.io), но более новый конкурент под названием Poetry (https://python-poetry.org) становится все популярнее.
Я использовал pip, Pipenv и Poetry, но теперь предпочитаю Poetry. Установить его можно с помощью команды pip install poetry. В Poetry есть множество дополнительных команд, таких как poetry add для добавления пакета в виртуальную среду, poetry install, чтобы загрузить и установить инструмент, и т.д. Просмотрите веб-сайт Poetry или запустите команду poetry, чтобы открыть раздел помощи.
Помимо загрузки отдельных пакетов, pip и Poetry управляют несколькими пакетами в файлах конфигурации — requirements.txt для pip и pyproject.toml для Poetry. Poetry и pip не просто загружают пакеты, но и управляют сложными зависимостями, которые могут существовать между пакетами. Вы можете задать желаемые варианты пакетов в виде минимумов, максимумов, диапазонов или точных значений, известных также как pinning или привязка. Этот вопрос может стать важным по мере роста проекта и изменения пакетов, от которых он зависит. Может понадобиться минимальная версия пакета, если используемая вами функция появилась в нем впервые, или максимальная, если функция была отменена.
Форматирование исходного кода менее важно, чем темы предыдущих разделов, но все же полезно. Избегайте споров о форматировании кода (bikeshedding) с помощью инструмента, приводящего исходный текст к стандартному, не странному формату. Хороший вариант выбора — пакет Black (https://black.read thedocs.io). Установить его можно с помощью команды pip install black.
Тестирование подробно рассматривается в главе 12. Хотя стандартным тестовым пакетом Python является unittest, промышленный тестовый пакет Python, используемый большинством разработчиков Python, — это pytest (https://docs.pytest.org). Установить его можно с помощью команды pip install pytest.
Почти универсальным решением для контроля исходного кода сейчас является Git с хранилищами (репозиториями) на таких сайтах, как GitHub и GitLab. Использование Git нельзя считать чем-то специфическим для Python или FastAPI, но, скорее всего, вы будете проводить с ним большую часть своего времени в процессе разработки. Инструмент pre-commit (https://pre-commit.com) запускает на вашей локальной машине различные тесты, такие как black и pytest, перед тем как выполнить коммит в Git. После размещения в удаленном репозитории Git можно запустить там больше тестов непрерывной интеграции (Continuous Integration, CI).
Более подробная информация содержится в главе 12 и в разделе «Устранение неполадок» главы 13.
В главе 3 показано, как установить и применять основные веб-инструменты Python, используемые в этой книге:
• FastAPI — сам веб-фреймворк;
• Uvicorn — асинхронный веб-сервер;
• HTTPie — текстовый веб-клиент, похожий на curl;
• Requests — пакет синхронного веб-клиента;
• HTTPX — пакет синхронного/асинхронного веб-клиента.
Модули и пакеты Python необходимы для создания больших приложений, которые не превращаются в «большие комки грязи» (https://oreil.ly/zzX5T). Даже в однопроцессном веб-сервисе можно сохранить описанное в главе 1 разделение с помощью тщательного проектирования модулей и импортов.
Встроенные структуры данных Python очень гибкие, и их очень заманчиво использовать повсюду. Но в следующих главах вы увидите, что можно определять модели более высокого уровня, чтобы сделать межуровневое взаимодействие более чистым. Эти модели опираются на относительно недавнее дополнение к Python, называемое подсказкой типов (type hinting). Давайте разберемся в этом вопросе, но сначала коротко о том, как Python работает с переменными. Это не помешает.
Термин «объект» получил множество определений в мире программного обеспечения, возможно, даже слишком много. В Python объект — это структура данных для упаковки каждого отдельного фрагмента данных в программе, от целого числа 5 до функции и всего, что вы можете определить. В нем, помимо прочей отчетной информации, указываются:
• уникальное идентификационное значение;
• низкоуровневый тип, соответствующий аппаратному обеспечению;
• конкретное значение (физические биты);
• подсчет количества переменных, ссылающихся на него.
Python строго типизирован на уровне объектов (тип объекта не меняется, хотя его значение может меняться). Объект называется изменяемым, если его значение может быть изменено, и неизменяемым, если нет.
На уровне переменных Python отличается от многих других вычислительных языков, и это может сбить с толку. Во многих других языках переменная — это, по сути, прямой указатель на область памяти, содержащую необработанное значение, хранящееся в битах, которые соответствуют аппаратному дизайну компьютера. Если вы присваиваете этой переменной новое значение, язык перезаписывает предыдущее значение в памяти новым.
Это прямое и быстрое решение. Компилятор следит за тем, что куда записывается. Это одна из причин того, почему такие языки, как C, быстрее Python. Как разработчику, вам необходимо убедиться, что вы присваиваете каждой переменной только значения правильного типа.
И здесь Python имеет существенное отличие — переменная в нем представляет собой просто имя, временно ассоциируемое с объектом более высокого уровня в памяти. Если вы присваиваете новое значение переменной, ссылающейся на неизменяемый объект, то фактически создаете новый объект, содержащий это значение, а затем получаете имя для ссылки на данный объект. Старый объект (на который раньше ссылалось имя) освобождается, и его память может быть восстановлена, если на него не ссылаются другие имена, то есть счетчик ссылок равен 0.
В книге «Простой Python» я сравниваю объекты с пластиковыми коробками, стоящими на полках памяти, а имена/переменные — со стикерами на этих коробках. Или вы можете представить имена как бирки, прикрепленные ниточками к этим коробкам.
Обычно при использовании имени вы присваиваете его одному объекту, и оно сохраняется за ним. Такая простая последовательность помогает понять ваш код. Область видимости переменной — это область кода, в которой имя ссылается на один и тот же объект, например, внутри функции. Вы можете применять одно и то же имя в разных областях видимости, но каждое из них будет ссылаться на разные объекты.
Можно сделать так, чтобы переменная ссылалась на разные объекты в программе Python, однако это не всегда хорошо. Не посмотрев, вы не узнаете, находится ли имя x в строке 100 в той же области видимости, что и имя x в строке 20. (Кстати, x — ужасный выбор имени переменной. Следует выбирать действительно значимые имена.)
Вся эта предыстория имеет определенный смысл.
В Python 3.6 добавлены подсказки типов (type hints) для объявления типа объекта, на который ссылается переменная. Они не выполняются интерпретатором Python во время его работы! Вместо этого их могут задействовать различные инструменты для обеспечения последовательного использования переменной. Стандартная программа проверки типов называется mypy, и позже я покажу вам, как она работает.
Подсказка типа может показаться просто приятной вещью, как и многие инструменты lint, помогающие программистам избежать ошибок. Например, она может напомнить, что ваша переменная count ссылается на объект Python типа int. Но подсказки, хотя они и представляют собой дополнительную возможность и являются необязательными примечаниями (буквально намеками), оказываются неожиданно полезными. Далее в этой книге вы увидите, как FastAPI адаптировал пакет Pydantic, чтобы грамотно использовать подсказки типов.
Добавление объявлений типов может стать тенденцией в других языках, ранее не имевших типов. Например, многие разработчики JavaScript перешли на TypeScript (https://www.typescriptlang.org).
Подробнее о Python и структурах данных вы узнаете в главе 5.
Помимо прочего, веб-фреймворк осуществляет перевод между байтами HTTP кода и структурами данных Python. Это поможет сэкономить много сил. В то же время если часть его работает не так, как вам нужно, то может понадобиться взломать решение. Как говорится, не надо изобретать колесо — разве что вы не можете найти круглое.
Web Server Gateway Interface (WSGI) (https://wsgi.readthedocs.io) — это спецификация стандарта синхронизации (https://peps.python.org/pep-3333) Python для подключения кода приложения к веб-серверам. Все традиционные веб-фреймворки Python построены на WSGI. Но синхронное взаимодействие может означать, что вы заняты ожиданием чего-то, что работает гораздо медленнее процессора, например запросов к дискам или сети. Тогда вы будете искать лучшую конкурентность. В последние годы она приобретает все большее значение. В результате была разработана спецификация Asynchronous Server Gateway Interface (ASGI) (https://asgi.readthedocs.io) для Python. Об этом рассказывается в главе 4.
Django (https://www.djangoproject.com) — это полнофункциональный веб-фреймворк, обозначающий себя как веб-фреймворк для перфекционистов с жесткими сроками выполнения работы. Он был анонсирован Адрианом Холовати и Саймоном Уиллисоном в 2003 году и назван в честь Джанго Рейнхардта — бельгийского джазового гитариста XX века. Django часто используется для корпоративных сайтов с базами данных. Более подробное описание приводится в главе 7.
Flask (https://flask.palletsprojects.com), представленный Армином Ронахером в 2010 году, является микрофреймворком. В главе 7 вы найдете более подробную информацию о нем и его сравнение с Django и FastAPI.
Встретив на балу других ухажеров, мы наконец-то сталкиваемся с интригующим FastAPI, о котором и пойдет речь в этой книге. Хотя FastAPI был опубликован Себастьяном Рамиресом в 2018 году, он уже поднялся на третье место среди веб-фреймворков Python, уступая лишь Flask и Django, и развивается все быстрее. Выполненное в 2022 году сравнение (https://oreil.ly/36WTQ) показывает, что в какой-то момент он может обойти конкурентов.
Перед вами данные о количестве звезд на GitHub по состоянию на конец октября 2023 года:
• Django — 73,8 тыс.;
• Flask — 64,8 тыс.;
• FastAPI — 64 тыс.
После тщательного изучения альтернативных вариантов (https://oreil.ly/JDDOm) Рамирес разработал дизайн (https://oreil.ly/zJFTX), по большей части основанный на двух сторонних пакетах Python:
• Starlette — для получения подробной информации о веб-странице;
• Pydantic — для получения подробной информации о данных.
А в готовый продукт он добавлял собственные ингредиенты и особые соусы. В следующей главе вам станет ясно, о чем идет речь.
В этой главе было рассмотрено множество вопросов, связанных с современным Python:
• полезные инструменты для веб-разработчика на Python;
• значимость API и сервисов;
• подсказки типов, объекты и переменные в Python;
• структуры данных для веб-сервисов;
• веб-фреймворки.
Любанович Б. Простой Python. Современный стиль программирования. 2-е изд. — СПб.: Питер, 2021.