Перейти к содержанию

Python проеты с Poetry и VSCode

Виртуальная среда — это изолированная установка Python, предназначенная для того, чтобы не заполнять нашу базовую среду библиотеками, которые мы могли бы использовать только для одного проекта. Это также позволяет нам управлять несколькими версиями одного и того же пакета в разных проектах. Например, нам может понадобиться Django 4.1 для одного и 1.9 для другого.

Poetry — это инструмент для установки зависимостей, а также сборки и упаковки пакетов Python. Для всего этого нужен только один файл: новый стандартизированный pyproject.toml. Другими словами, poetry использует pyproject.toml для замены setup.py, requirements.txt, setup.cfg, MANIFEST.in и недавно добавленного Pipfile.

В этой серии статей мы будем использовать Poetry для управления нашими зависимостями, создания простого проекта и с помощью одной команды опубликуем его на PyPI.

В первой части мы:

  • Создадим новый проект.
  • Создадим виртуальную среду.
  • Настроим зависимостями.

Во второй части мы:

  • Добавьте нашу виртуальную среду в VSCode.
  • Интегрируем наши зависимости для разработчиков:
  • Flake8
  • Black
  • Pytest

И, наконец, в третьей части мы:

  • Напишите пример библиотеки.
  • Создайте наш проект с Poetry.
  • Опубликуйте его на PyPI.

Установка Poetry

Самый простой способ — использовать pip:

$ pip install poetry

Но мы будем использовать собственный установщик Poetry, чтобы изолировать его от остальной системы, продав его зависимости. Это рекомендуемый способ установки poetry:

$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -

Таким образом, позже мы сможем обновить поэзию до последней стабильной версии с помощью команды poetry self update.

Запуск нового проекта

Теперь мы можем начать новый проект Python, используя команду poetry new [project_name]. Я назову его how-long и это будет простая библиотека для измерения времени выполнения функции:

$ poetry new how-long

Примечание. Для существующих проектов вы можете использовать команду poetry init и в интерактивном режиме создать pyproject.toml.

Создаться каталог, how-long и внутри представляет собой базовую структуру проекта:

how-long
├── README.rst
├── how_long
│   └── __init__.py
├── pyproject.toml
└── tests
    ├── __init__.py
    └── test_how_long.py

Примечание. Чтобы иметь возможность опубликовать свой проект, вам необходимо доступное имя. Используйте поиск PyPI для этого.

Файл pyproject.toml

Файл pyproject.toml будет управлять деталями и зависимостями проекта:

[tool.poetry]
name = "how-long"
version = "0.1.0"
description = "A simple decorator to measure a function execution time."
authors = ["wilfredinni <carlos.w.montecinos@gmail.com>"]

[tool.poetry.dependencies]
python = "^3.7"

[tool.poetry.dev-dependencies]
pytest = "^3.0"

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

[tool.poetry]

Детали. Добавление license и README может быть хорошей идеей:

[tool.poetry]
...
license = "MIT"
readme = "README.rst"

[tool.poetry.dependencies]

Во-первых, это версия Python. По сути, этот проект будет совместим с Python 3.7 и выше. Кроме того, отныне каждый устанавливаемый нами пакет, предназначенный для использования в рабочей среде, будет отображаться здесь.

[tool.poetry.dev-dependencies]

Эти пакеты предназначены только для разработки и не будут включены при публикации нашего проекта. По умолчанию Poetry включает Pytest, поэтому мы будем использовать его для тестирования нашего проекта позже.

Создание виртуальной среды

Чтобы создать виртуальную среду и установить Pytest, мы будем использовать команду poetry install:

$ poetry install

После этого будет создан новый файл poetry.lock .

Когда Poetry завершит установку, он запишет все пакеты и их точные версии, которые он загрузил, в файл poetry.lock, привязав проект к этим конкретным версиям. Вы должны зафиксировать файл поэзии.lock в репозитории вашего проекта, чтобы все люди, работающие над проектом, были привязаны к одним и тем же версиям зависимостей.

Управление зависимостями

Один из способов добавить или удалить зависимости — напрямую отредактировать файл pyproject.toml, а затем запустить poetry install, чтобы применить изменения. Вместо этого мы будем использовать команды add и remove, чтобы избежать ручных изменений.

Добавление зависимостей

Добавим в проект два пакета, pendulum, и coo:

$ poetry add pendulum coo

Откройте pyproject.toml и poetry.lock и посмотрите, как они обновились.

Добавление зависимостей для разработчиков

Эти зависимости будут доступны только во время разработки, Poetry не будет включать их при сборке и публикации проекта.

Мы уже установили Pytest, но также будем использовать flake8 для линтинга и mypy для статической типизации:

$ poetry add -D flake8 mypy

Теперь, когда я думаю об этом, я забыл добавить форматтер. Мы пойдем с black:

$ poetry add -D black
[ValueError]
Could not find a matching version of package black

add [-D|--dev] [--git GIT] [--path PATH] [-E|--extras EXTRAS] [--optional] [--python PYTHON] [--platform PLATFORM] [--allow-prereleases] [--dry-run] [--] <name> (<name>)...

Эта ошибка возникает из-за того, что black находится в состоянии предварительного выпуска, поэтому Poetry не может найти для нас стабильную версию. Но я очень этого хочу, так что давайте все равно установим его с флагом --allow-prereleases:

$ poetry add -D black --allow-prereleases

Удаление зависимостей

Знаете что, я передумал, в этом проекте не будут использоваться ни coo, ни mypy. Начните с удаления coo, обычной зависимости нашего проекта:

$ poetry remove coo

Теперь mypy, который является зависимостью от разработчиков:

$ poetry remove -D mypy

Мы начали новый проект, создали виртуальную среду и добавили и удалили зависимости с помощью следующих команд:

Command Description
poetry new [package-name] Запустите новый проект Python.
poetry init Создайте файл pyproject.toml в интерактивном режиме.
poetry install Установите пакеты внутри файла pyproject.toml.
poetry add [package-name] Добавьте пакет в виртуальную среду.
poetry add -D [package-name] Добавьте пакет разработки в виртуальную среду.
poetry remove [package-name] Удалить пакет из виртуальной среды.
poetry remove -D [package-name] Удалите пакет разработки из виртуальной среды.
poetry self:update Обновите поэзию до последней стабильной версии.

Далее мы увидим больше команд Poetry, добавим нашу виртуальную среду в VSCode и используем установленные нами пакеты для разработки (Flake8), форматирования (Black) и тестирования (Pytest) нашего кода внутри редактора. Наконец, в третьем мы напишем и опубликуем образец библиотеки в PyPI.

Настройка Poetry на VSCode

Стоит проверить наличие новых версий наших зависимостей. Откройте свой терминал, перейдите в каталог вашего проекта и введите команду poetry update:

Пока новых версий нет.

Когда вы создаете виртуальную среду с помощью команды venv, VSCode автоматически устанавливает ее в качестве среды Python по умолчанию для этого проекта. При работе с Poetry в первый раз нам нужно будет ввести следующее в терминале и внутри папки проекта:

$ poetry shell
$ code .

Первая команда, poetry shell, создаст нас внутри нашей виртуальной среды, а code . откроет текущую папку внутри VSCode.

vscode

Откройте папку how-long (или папку с названием вашего проекта) с помощью левой панели и рядом с __init__.py создайте файл how-long.py. В левом нижнем углу вы увидите текущую среду Python:

python version

Щелкните ее, и отобразится список доступных сред. Выберите тот, в котором есть название вашего проекта:

choose python

Теперь давайте интегрируем наши зависимости разработки, Flake8, Black, и Pytest в Visual Studio Code.

Flake8

Flake8 предоставит нашим проектам возможности линтинга. Другими словами, предупреждение об ошибках синтаксиса и стиля, а благодаря VSCode мы узнаем их по мере ввода.

По умолчанию расширение Python поставляется с включенным Pylint, который является мощным, но сложным в настройке. Чтобы переключиться на Flake8, внесите изменения в любой файл Python и сохраните его. В правом нижнем углу появится всплывающее сообщение:

flake8

Нажмите Select Linter и выберите Flake8 из списка. Теперь VSCode сообщит нам о наших проблемах с синтаксисом и стилем, зеленым или красным в зависимости от их серьезности, всегда с хорошим описанием того, что не так:

linting

Похоже, у нас есть две проблемы: мы пропустили пустую строку в конце нашего файла (style) и забыли добавить кавычки к нашему Hello, World! строка (syntax). Исправьте их, и все предупреждения исчезнут.

Black

Black это средство форматирования кода, инструмент, который просматривает наш код и автоматически форматирует его в соответствии с руководством по стилю PEP 8, тем же PEP, который использует Flake8 для проверки наших ошибок стиля.

Удерживайте shift + cmd/ctrl + p, чтобы открыть палитру команд, введите Format Document и нажмите клавишу ВВОД. Появится новое всплывающее сообщение:

black formatter popup

Выберите Use Black. Теперь скопируйте этот плохо отформатированный код в ваш файл Python:

for i in range(5):         # this comment has too many spaces
      print(i)  # this line has 6 space indentation.

Какой уродливый кусок дерьмового кода s***.... Попробуйте отформатировать его еще раз и посмотрите, как Black исправит их все за вас!

Еще мы можем настроить VSCode так, чтобы при каждом сохранении Black автоматически форматировал наш код. Удерживайте cmd/ctrl + , чтобы открыть настройки. Убедитесь, что вы находитесь в Workspace Settings, найдите Format On Save и установите флажок:

format on save

Наконец, Black по умолчанию использует 88 символов в строке, в отличие от 80, разрешенных Flake8, поэтому, чтобы избежать конфликтов, откройте папку .vscode и добавьте следующее в конец файла settings.json:

{
    ...
    "python.linting.flake8Args": [
        "--max-line-length=88"
    ],
}

black-settings

Pytest

Если вы серьезно относитесь к программированию, вам крайне важно научиться тестировать свои проекты. Это невероятно полезный навык, который позволяет вам писать и выпускать программы с уверенностью, снижая вероятность появления катастрофических ошибок после выпуска.

Pytest — очень популярный и удобный фреймворк для написания тестов. Мы уже установили его, поэтому мы также будем интегрировать его с VSCode.

Откройте папку с tests и выберите файл test_how_long.py. Poetry уже дает нам первое испытание:

# test_how_long.py
from how_long import __version__


def test_version():
    assert __version__ == '0.1.0'

В этом тесте мы импортируем переменную __version__ из файла __init__.py, который находится в папке how_long, и утверждаем, что текущая версия — 0.1.0. Откройте встроенный терминал, выбрав Terminal > New Terminal и введите:

$ pytest

Вывод будет выглядеть так:

pytest

Хорошо, все в порядке. Откройте палитру команд с помощью shift + cmd/ctrl + p:

  • Напишите unit и выберите Python: Configure Unit Tests.
  • Выберите pytest.
  • Выберите каталог, в котором вы сохранили тесты, в нашем случае tests.

Произошло три вещи:

  • В строке состояния появилась новая кнопка: Run Tests. Это то же самое, что ввести pytest в терминале. Нажмите ее и выберите Run All Unit Tests. Когда закончите, он сообщит вам количество пройденных тестов и тестов, которые не пройдены:

test status bar

  • Новая иконка на левой панели. Если вы нажмете на нее, появится панель, отображающая все тесты. Здесь вы можете запустить каждый из них по отдельности:

test side panel

  • Внутри тестового файла перед каждой тестовой функцией будут отображаться новые параметры: появится значок проверки, если все в порядке, и x в противном случае. Он также позволяет запускать определенные тесты:

test inline

Выше мы начали новый проект, создали виртуальную среду и управляли зависимостями. Далее мы добавили нашу виртуальную среду в VSCode и интегрировали наши зависимости от разработчиков.

И, наконец, теперь мы:

  • Напишем пример библиотеки.
  • Создадим наш проект с Poetry.
  • Опубликуем его на PyPI.

Вот таблица с командами, используемыми в этой серии, а также их описания. Полный список см. в Документации по поэзии.

Poetry команды

Вот таблица с командами, которые мы еще не использовали, а также их описания. Полный список см. в Poetry документации.

Command Description
poetry update Получить последние версии зависимостей
poetry shell Создает оболочку в виртуальной среде.
poetry build создает архивы исходников .
poetry publish Опубликовать пакет в Pypi.
poetry publish --build Создайте и опубликуйте пакет.

Проект

Это будет простой декоратор, который выведет на консоль время, необходимое для запуска функции.

Это будет работать следующим образом:

from how_long import timer

@timer
def test_function():
    [i for i in range(10000)]

test_function()
# Execution Time: 955 ms.

Это будет работать следующим образом:

how-long
├── how_long
│   ├── how_long.py
│   └── __init__.py
├── how_long.egg-info
│   ├── dependency_links.txt
│   ├── PKG-INFO
│   ├── requires.txt
│   ├── SOURCES.txt
│   └── top_level.txt
├── LICENSE
├── poetry.lock
├── pyproject.toml
├── README.rst
└── tests
    ├── __init__.py
    └── test_how_long.py

Перед тем, как мы начнем, проверьте наличие обновлений пакетов с помощью команды poetry update:

poetry update

Добавьте краткое описание проекта в файл README.rst:

how_long
========

Simple Decorator to measure a function execution time.

Example
_______

.. code-block:: python

    from how_long import timer


    @timer
    def some_function():
        return [x for x in range(10_000_000)]

Перейдите к файлу how_long/how_long.py:

# how_long.py
from functools import wraps

import pendulum


def timer(function):
    """
    Simple Decorator to measure a function execution time.
    """

    @wraps(function)
    def function_wrapper():
        start = pendulum.now()
        function()
        elapsed_time = pendulum.now() - start
        print(f"Execution Time: {elapsed_time.microseconds} ms.")

    return function_wrapper

В how_long/__init__.py:

from .how_long import timer

__version__ = "0.1.1"

И, наконец, в файл tests/test_how_long.py:

from how_long import __version__
from how_long import timer


def test_version():
    assert __version__ == "0.1.1"


def test_wrap():
    @timer
    def wrapped_function():
        return

    assert wrapped_function.__name__ == "wrapped_function"

Теперь вы можете использовать poetry install на своем терминале, чтобы установить и проверить свой пакет локально. Активируйте вашу виртуальную среду, если вы еще этого не сделали, и в интерактивной оболочке Python:

>>> from how_long import timer
>>>
>>> @timer
... def test_function():
...     [i for i in range(10000)]
...
>>> test_function()
Execution Time: 705 ms.

Запустите тесты и, если все в порядке, двигайтесь дальше.

Создание и публикация

Наконец-то пришло время сделать этот проект доступным для всего мира! Убедитесь, что у вас есть учетная запись на PyPI. Помните, что имя пакета должно быть уникальным, если вы не уверены, воспользуйтесь поиском, чтобы проверить его.

Сборка

Команда poetry build создает архивы исходного кода и wheels, которые позже будут загружены в качестве исходного кода проекта:

poetry build

Будет создан каталог how_long.egg-info.

Публикация

Эта команда публикует пакет в PyPI и автоматически регистрирует его перед загрузкой, если он отправляется впервые:

poetry publish

Вы также можете создать и опубликовать свой проект с помощью $ poetry publish --build.

Введите свои учетные данные и, если все в порядке, просмотрите свой проект, и вы увидите что-то вроде этого:

Теперь мы можем сообщить другим, что они могут установить pip install how-longи с любой машины и из любого места!