Основные библиотеки Python, которых вам не хватает

Известно, что Python поставляется с «батарейками в комплекте» благодаря его очень обширной стандартной библиотеке, которая включает в себя множество модулей и функций, которых вы не ожидаете. Тем не менее, есть ещё много полезных библиотек, о которых вы должны знать и которые вы должны использовать во всех своих проектах Python, и вот их список.

Утилиты общего назначения

Мы начнём с пары библиотек общего назначения, которые вы можете использовать во многих проектах. Первая описана в документах как:

«Boltons — это набор утилит на чистом Python в том же духе, что и в стандартной библиотеке, но явно отсутствующий в ней».

Нам понадобилась бы целая статья, чтобы рассмотреть каждую функцию и особенность boltons, но вот пара примеров удобных функций:

# pip install boltons
from boltons import jsonutils, timeutils, iterutils
from datetime import date

# {"name": "John", "id": 1, "active": true}
# {"name": "Ben", "id": 2, "active": false}
# {"name": "Mary", "id": 3, "active": true}
with open('input.jsonl') as f:
    for line in jsonutils.JSONLIterator(f):  # Automatically converted to dict
        print(f"User: {line['name']} with ID {line['id']} is {'active' if line['active'] else 'inactive'}")
        # User: John with ID 1 is active
        # ...

start_date = date(year=2023, month=4, day=9)
end_date = date(year=2023, month=4, day=30)

for day in timeutils.daterange(start_date, end_date, step=(0, 0, 2)):
    print(repr(day))
    # datetime.date(2023, 4, 9)
    # datetime.date(2023, 4, 11)
    # datetime.date(2023, 4, 13)

data = {"deeply": {"nested": {"python": {"dict": "value"}}}}
iterutils.get_path(data, ("deeply", "nested", "python"))
# {'dict': 'value'}

data = {"id": "234411",
        "node1": {"id": 1234, "value": "some data"},
        "node2": {"id": "2352345", 
                  "node3": {"id": "123422", "value": "more data"}
                  }
        }

iterutils.remap(data, lambda p, k, v: (k, int(v)) if k == 'id' else (k, v))

Хотя стандартная библиотека Python имеет модуль json, она не поддерживает формат JSON Lines (.jsonl). В первом примере показано, как вы можете обрабатывать jsonl с помощью библиотеки boltons.

Второй пример демонстрирует модуль boltons.timeutils, который позволяет создавать диапазоны дат. Вы можете перебрать их и установить аргумент step, например, получать через день. Опять же, это то, чего не хватает в модуле Python datetime.

Наконец, в третьем примере мы используем функцию remap из модуля boltons.iterutils для рекурсивного преобразования всех полей id словаря в целые числа. Здесь boltons.iterutils служит хорошим расширением для встроенного itertools.

Говоря о iterutils и itertools, следующая отличная библиотека, которую вам нужно проверить, это more-itertools , которая предоставляет гораздо больше itertools.

Последней в этой категории является библиотека sh, которая является заменой модуля subprocess. Будет здорово, если вы обнаружите, что в Python вы управляете множеством других процессов:

# https://pypi.org/project/sh/
# pip install sh
import sh

# Run any command in $PATH...
print(sh.ls('-la'))
# total 36
# drwxrwxr-x  2 martin martin  4096 apr  8 14:18 .
# drwxrwxr-x 41 martin martin 20480 apr  7 15:23 ..
# -rw-rw-r--  1 martin martin    30 apr  8 14:18 examples.py

with sh.contrib.sudo:
    # Do stuff using 'sudo'...
    ...

# Write to a file:
sh.ifconfig(_out='/tmp/interfaces')

# Piping:
print(sh.wc('-l', _in=sh.ls('.', '-1')))
# Same as 'ls -1 | wc -l'

Когда мы вызываем sh.some_command, библиотека sh пытается найти встроенную команду shell или двоичный файл $PATH с таким именем. Если она найдёт такую ​​команду, она просто выполнит её для вас.

Если вам нужно использовать sudo, вы можете использовать контекстный менеджер sudo из модуля contrib, как показано во второй части фрагмента.

Чтобы записать вывод команды в файл, вам нужно только указать аргумент _out. И, наконец, вы также можете использовать каналы ( |) с помощью аргумента _in.

Валидация данных

Ещё одна недостающая часть в стандартной библиотеке Python — это категория инструментов проверки данных. Одна небольшая библиотека, обеспечивающая это, называется validators. Эта библиотека позволяет вам проверять общие шаблоны, такие как электронные письма, IP-адреса или кредитные карты:

# https://python-validators.github.io/validators/
# pip install validators
import validators

validators.email('someone@example.com')  # True
validators.card.visa('...')
validators.ip_address.ipv4('1.2.3.456')  # ValidationFailure(func=ipv4, args={'value': '1.2.3.456'})

Далее идёт нечёткое сравнение строк — difflib, но этот модуль нуждается в некоторых улучшениях. Некоторые из них можно найти в библиотеке thefuzz (ранее известной как fuzzywuzzy):

# pip install thefuzz
from thefuzz import fuzz
from thefuzz import process

print(fuzz.ratio("Some text for testing", "text for some testing"))  # 76
print(fuzz.token_sort_ratio("Some text for testing", "text for some testing"))  # 100
print(fuzz.token_sort_ratio("Some text for testing", "some testing text for some text testing"))  # 70
print(fuzz.token_set_ratio("Some text for testing", "some testing text for some text testing"))  # 100

songs = [
    '01 Radiohead - OK Computer - Airbag.mp3',
    '02 Radiohead - OK Computer - Paranoid Android.mp3',
    '04 Radiohead - OK Computer - Exit Music (For a Film).mp3',
    '06 Radiohead - OK Computer - Karma Police.mp3',
    '10 Radiohead - OK Computer - No Surprises.mp3',
    '11 Radiohead - OK Computer - Lucky.mp3',
    '02 Radiohead - Pablo Honey - Creep.mp3',
    '04 Radiohead - Pablo Honey - Stop Whispering.mp3',
    '06 Radiohead - Pablo Honey - Anyone Can Play Guitar.mp3',
    "10 Radiohead - Pablo Honey - I Can't.mp3",
    '13 Radiohead - Pablo Honey - Creep (Radio Edit).mp3',
    # ...
]
print(process.extract("Radiohead - No Surprises", songs, limit=1, scorer=fuzz.token_sort_ratio))
# [('10 Radiohead - OK Computer - No Surprises.mp3', 70)]

Привлекательность библиотеки thefuzz заключается в функциях *ratio, которые, вероятно, будут работать лучше, чем встроенные difflib.get_close_matches или difflib.SequenceMatcher.ratio. Фрагмент выше показывает их различное использование. Во-первых, мы используем базовый ratio, который вычисляет простую оценку сходства двух строк. После этого мы используем token_sort_ratiowhich, игнорируя порядок токенов (слов) в строке при вычислении сходства. Наконец, мы тестируем функцию token_set_ratio, которая вместо этого игнорирует повторяющиеся токены.

Мы также используем функцию extract из модуля process, которая является альтернативой difflib.get_close_matches. Эта функция ищет наилучшее совпадение в списке строк.

Если вы уже используете difflib и думаете, стоит ли вам использовать thefuzz вместо этого, то обязательно ознакомьтесь со статьей автора библиотеки, в которой хорошо показано, почему встроенных функций difflib не всегда достаточно и почему приведённые выше функции могут работать лучше.

Отладка

Довольно много библиотек отладки и устранения неполадок также обеспечивают превосходные возможности по сравнению со стандартными библиотеками. Одной из таких библиотек является stackprinter, которая предоставляет более полезные версии встроенных сообщений об исключениях Python:

# pip install stackprinter

import stackprinter
stackprinter.set_excepthook(style='darkbg2')

def do_stuff():
    some_var = "data"
    raise ValueError("Some error message")

do_stuff()

Всё, что вам нужно сделать, чтобы использовать её, это импортировать её и установить ловушку исключения. Затем запуск кода, выдающего исключение, приведёт к следующему:

Основные библиотеки Python, которых вам не хватает

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

stackprinter помогает с отладкой проблем, которые приводят к исключениям, но это лишь небольшая часть проблем, которые мы все отлаживаем. В большинстве случаев поиск и устранение ошибок включает в себя просто размещение операторов printor logпо всему коду, чтобы увидеть текущее состояние переменных или был ли запущен код. И есть библиотека, которая может улучшить отладку print в базовом стиле:

# pip install icecream
from icecream import ic

def do_stuff():
    some_var = "data"
    some_list = [1, 2, 3, 4]
    ic()
    return some_var

ic(do_stuff())
# ic| examples.py:46 in do_stuff() at 11:27:44.604
# ic| do_stuff(): 'data'

Она называется icecream и предоставляет функцию ic, которая служит заменой print. Вы можете использовать простой код ic()(без аргументов), чтобы проверить, какие части кода были выполнены. В качестве альтернативы вы можете использовать ic(some_func(...)), которая будет выводить функцию/выражение вместе с возвращаемым значением.

Дополнительные параметры и настройки см. в GitHub README .

Тестирование

Говоря об отладке, мы также должны упомянуть тестирование. Я не собираюсь советовать вам использовать другие тестовые фреймворки вместо встроенных unittest (даже если они просто лучше), вместо этого я хочу показать вам три небольших полезных инструмента:

Первая — это библиотека freezegun, которая позволяет вам тестировать datetime:

# pip install pytest freezegun
from freezegun import freeze_time
import datetime

# Run 'pytest' in shell
@freeze_time("2022-04-09")
def test_datetime():
    assert datetime.datetime.now() == datetime.datetime(2022, 4, 9)  # Passes!


def test_with():
    with freeze_time("Apr 9th, 2022"):
        assert datetime.datetime.now() == datetime.datetime(2022, 4, 9)  # Passes!


@freeze_time("Apr 9th, 2022", tick=True)
def test_time_ticking():
    assert datetime.datetime.now() > datetime.datetime(2022, 4, 9)  # Passes!

Всё, что вам нужно сделать, это добавить декоратор к функции test, которая устанавливает дату (или datetime). Кроме того, вы также можете использовать её в качестве диспетчера контекста ( оператор with).

Выше вы также можете увидеть, что она позволяет указать дату в удобном формате. И, наконец, вы также можете передать tick=True, что перезапустит время с заданного значения.

При желании, если вы используете pytest, вы также можете установить pytest-freezegun для фикстур в стиле Pytest.

Второй важной библиотекой/помощником для тестирования, который вам нужен, является dirty-equals. Она предоставляет вспомогательные функции равенства для сравнения вещей, которые вроде как равны:

# pip install dirty-equals
from dirty_equals import IsApprox, IsNow, IsJson, IsPositiveInt, IsPartialDict, IsList, AnyThing
from datetime import datetime

assert 1.0 == IsApprox(1)
assert 123 == IsApprox(120, delta=4)  # close enough...

now = datetime.now()
assert now == IsNow  # just about...

assert '{"a": 1, "b": 2}' == IsJson
assert '{"a": 1}' == IsJson(a=IsPositiveInt)

assert {'a': 1, 'b': 2, 'c': 3} == IsPartialDict(a=1, b=2)  # Validate only subset of keys/values

assert [1, 2, 3] == IsList(1, AnyThing, 3)

Выше приведён пример помощников, которые проверяют, являются ли два целых числа или datetimes примерно одинаковыми; является ли что-то допустимым JSON, включая тестирование отдельных ключей в этом JSON, или является ли значение словарём или списком с определёнными ключами/значениями.

И, наконец, третья полезная библиотека называется pyperclip. Она предоставляет функции для копирования и вставки в/из буфера обмена. Я нахожу это очень полезным для отладки, например, для копирования значений переменных или сообщений об ошибках в буфер обмена, но у этого может быть много других вариантов использования:

# pip install pyperclip
# sudo apt-get install xclip
import pyperclip
try:
    print("Do something that throws error...")
    raise SyntaxError("Something went wrong...")
except Exception as e:
    pyperclip.copy(str(e))

# CTRL+V -> Something went wrong...

В этом фрагменте мы используем автоматическое копирование сообщения об исключении в буфер обмена pyperclip.copy, чтобы нам не приходилось копировать его вручную из результата программы.

CLI

Последняя категория, заслуживающая упоминания, — инструменты CLI. Если вы создаёте приложения CLI на Python, вы можете найти хорошее применение tqdm. Эта небольшая библиотека предоставляет индикатор выполнения для ваших программ:

# pip install tqdm
from tqdm import tqdm, trange
from random import randint
from time import sleep

for i in tqdm(range(100)):
    sleep(0.05)  # 50ms per iteration

# 0%  |          | 0/100 [00:00<?, ?it/s]
# 100%|██████████| 100/100 [00:05<00:00, 19.95it/s]

with trange(100) as t:
    for i in t:
        t.set_description('Step %i' % i)
        t.set_postfix(throughput=f"{randint(100, 999)/100.00}Mb/s", task=i)
        sleep(0.05)

# Step 60:  60%|██████    | 60/100 [00:03<00:02, 19.78it/s, task=60, throughput=4.06Mb/s]

Чтобы использовать её, мы заключаем цикл в tqdm и получаем индикатор выполнения в выводе программы. В более сложных случаях вы можете использовать диспетчер контекста trange и установить дополнительные параметры, такие как описание или любые настраиваемые поля индикатора выполнения, такие как пропускная способность или истёкшее время.

Модуль также может быть запущен как команда оболочки ( python -m tqdm), что может быть полезно, например, при создании резервной копии tar или поиске файлов с расширением find.

Дополнительные примеры и такие моменты, как интеграция с Pandas или Jupyter Notebook, см. в документации .

Заключение

С Python вы всегда должны искать существующие библиотеки, прежде чем внедрять что-либо с нуля. Если вы не создаёте особенно необычное или индивидуальное решение, скорее всего, кто-то уже создал его и выложил в PyPI.

В этой статье я перечислил только библиотеки общего назначения, которыми может воспользоваться каждый, но есть и много других специализированных, например, для машинного обучения или веб-разработки. Я бы порекомендовал вам заглянуть на https://github.com/vinta/awesome-python , где есть обширный список интересных библиотек, или вы также можете просто поискать PyPI по категориям , и я уверен, что вы найдёте там что-то полезное!

+1
0
+1
0
+1
0
+1
0
+1
0

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *