Pull to refresh

Подборка полезных библиотек для Python с примерами #1

Reading time9 min
Views18K

У Python одно из самых больших комьюнити. Этот язык любят за его простоту, лояльность и за его универсальность, которая была достигнута созданием огромного числа библиотек и фреймворков, таких как numpy, django, flask, pygame, tornado, tensorflow и других. На сайте pypi содержится более 320 тысяч проектов от малоизвестных и заброшенных до огромных, которыми пользуются миллионы людей в различных сферах. 

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

Библиотеки, рассмотренные в статье:

mutagen

⭐ github: 849

Данная библиотека позволяет извлекать всю основную информацию об аудиофайле, например, длину, битрейт, исполнителя и другие дополнительные теги. Для того, чтобы установить mutagen достаточно выполнить pip install mutagen. Mutagen поддерживает формат метаданных ID3v2, работая с форматом фреймом, определенном версией ID3v2.4 (включая информацию о RVA2 и POPM, см. теги ID3v2 подробнее тут), и формат APEv2 Также данная библиотека имеет простой и понятный API и удобную структуру хранения тегов. Вот несколько пример:

Получение информации об аудио
import mutagen

# загружаем сам файл
mfile = mutagen.File("E:/Reamon-Super Girl.mp3")

# выводим общую информацию
print(mfile.info.pprint())
>>> MPEG 1 layer 3, 160000 bps (CBR?), 44100 Hz, 2 chn, 243.83 seconds
print("Длина аудио (сек):", mfile.info.length)
print("Частота дискретизации:", mfile.info.sample_rate)
print("Битрейт:", mfile.info.bitrate)
print("Каналов:", mfile.info.channels)
>>> Длина аудио (сек): 243.83335
>>> Частота дискретизации: 44100
>>> Битрейт: 160000
>>> Каналов: 2
Работа с тегами
from mutagen.id3 import ID3

audio = ID3("E:/Reamon-Super Girl.mp3")

print("Название:", audio.get("TIT2"))
print("Тип носителя:", audio.get("TMED"))
print("Исполнитель:", audio.get("TPE1"))
>>> Название: Super Girl
>>> Тип носителя: DIG
>>> Исполнитель: Reamon

# общая информация
print(audio.pprint())
>>> TIT2=Super Girl TMED=DIG TPE1=Reamon
# удаляем все теги
audio.delete()
audio.save()
print(audio.pprint() == "")
>>> True

В отличие от многих других библиотек mutagen позволяет вызовом всего одной функции получить всю необходимую информацию об аудио в удобно читаемом формате.

in_place

⭐ github: 20

Бывают моменты, когда необходимо считать данные с файла, изменить их и перезаписать в тот же файл. В такие моменты приходится либо хранить данные в буфере в оперативной памяти, либо создавать новый файл и работать сразу с 2мя файлами. Модуль in_place берет на себя работу с временными файлами, благодаря чему новый файл будет носить такое же название. Для начала работы достаточно установить модуль: pip install in_place

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

import in_place
with in_place.InPlace('tmp.txt', encoding="utf-8") as fp:
    for line in fp:
        words = []
        for word in line.split():
            for char in "1234567890":
                word = word.replace(char, "")
            words.append(word)
        fp.write(" ".join(words) + "\n")
Исходный файл с грязным текстом
Исходный файл с грязным текстом
Исходный файл с очищенным текстом
Исходный файл с очищенным текстом

При таком подходе исходный файл удалится, но если в примере выше заменить строку with in_place.InPlace('tmp.txt', encoding="utf-8") as fp: на with in_place.InPlace('tmp.txt', encoding="utf-8", backup=”tmp_old.txt”) as fp:, то исходный файл сохранится с названием tmp_old.txt

with in_place.InPlace('tmp.txt', encoding="utf-8", backup="tmp_old.txt") as fp:
    for line in fp:
        words = []
        for word in line.split():
            for char in "1234567890":
                word = word.replace(char, "")
            words.append(word)
        fp.write(" ".join(words) + "\n")
Пример с сохранением бэкапа исходного файла
Пример с сохранением бэкапа исходного файла

Также класс InPlace может принимать еще несколько модификаторов:

  • mode=<'b'|'t'|None> - тип файла, ‘b’ - бинарный, ‘t’/None - текстовый

  • backup=<PATH> - путь к оригиналу файла

  • backup_ext=<EXTENSION> - создаст бэкап с именем файла + backup_ext

  • move_first=<BOOL> - меняет поведение при создании временных файлов

pyarmor

⭐ github: 1149

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

Существует хорошая и удобная библиотека pyarmor, которая позволит в пару кликов провести обфускацию кода. Данная библиотека может работать как из консоли, так и через собственный графический интерфейс. Для её использования достаточно выполнить: pip install pyarmor - для работы из консоли и pip install pyarmot-webui для установки графического интерфейса.

Создадим в некоторой папке “pyarm” два файла с кодом, первый файл назовём “one_module.py” с кодом:

class FileClass:
    def __init__(self, filename):
        self.filename = filename
    def clearFileName(self):
        newFName = ""
        for char in self.filename:
            if not char in "1234567890":
                newFName += char
        self.filename = newFName
    def saveToFile(self, posx, posy):
        with open(self.filename, "a", encoding="utf-8") as fp:
            fp.write(f"{posx} {posy}\n")

И main.py:

from one_module import FileClass
class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.fClass = FileClass("test.txt")
    def getNextValues(self, i):
        self.x = self.x*(self.y**i)
        self.y = self.y*(self.x**i) - self.x/i
        return self.x, self.y
    def saveNewValues(self, i):
        x,y = self.getNextValues(i)
        self.fClass.saveToFile(x,y)
if __name__ == "__main__":
    myClass = MyClass(2, 6.6)
    myClass.saveNewValues(5)

Далее в консоли запустим pyarmor, выполнив команду pyarmor-webui, после чего в браузере откроется главное меню:

Далее зайдем в раздел “Obfuscate Script Wizard”, в нем пропишем путь к директории с файлами и основной файл:

Далее нажмем “next” и пропишем дополнительный настройки, что необходимо рекурсивно в папке обфусцировать все файлы:

И нажмем “obfuscate”. В папке “pyarm” появится папка “dist”,  в которой будут лежать обфусцированые файлы. Посмотрим, что в них:

Можно запустить main.py и убедиться, что все работает, как надо. Алгоритм отработал так же, как и до изменения кода:

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

pyspellcheker

⭐ github: 400

Если у вас есть приложение, которое обрабатывает текстовые данные, например, принимает запросы от пользователя в виде текста (набора слов) и отбирает данные по этому тексту или есть приложение, которое статистически обрабатывает слова в тексте, то всегда может возникнуть проблема неправильного написания слов. В таком случае может помочь библиотека pyspellcheker. Установить её довольно просто, достаточно выполнить pip install pyspellchecker. Данный модуль помогает исправлять орфографические ошибки в словах. Ниже приведен код работы библиотеки с описанием:

Пример использования библиотеки
from spellchecker import SpellChecker

spell = SpellChecker(language='ru')
# так же можно установить количество ошибок в слове, 
# которое необходимо исправить
spell.distance = 1

words = ['локоть', 'человек', 'лакать', 'кнуть']
# проверить, каких слов нет в словаре
unkn_words = spell.unknown(words)
print("НЕИЗВЕСТНЫЕ СЛОВА:", unkn_words)

# проверить, какие слова есть в словаре
good_words = spell.known(words)
print("ИЗВЕСТНЫЕ СЛОВА:", good_words)
>>> НЕИЗВЕСТНЫЕ СЛОВА: {'кнуть', 'лакать'}
>>> ИЗВЕСТНЫЕ СЛОВА: {'человек', 'локоть'}

print("-"*20)
for word in words:
    print("СЛОВО:", word)
    # исправить ошибку в слове на наиболее лучший результат
    print("ИСПРАВЛЕНО НА:", spell.correction(word))
    # получить наиболее приоритетные варианты исправления слова
    print("ВАРИАНТЫ:", spell.candidates(word))
    print("-"*20)

>>> --------------------
>>> СЛОВО: локоть
>>> ИСПРАВЛЕНО НА: локоть
>>> ВАРИАНТЫ: {'локоть'}
>>> --------------------
>>> СЛОВО: человек
>>> ИСПРАВЛЕНО НА: человек
>>> ВАРИАНТЫ: {'человек'}
>>> --------------------
>>> СЛОВО: лакать
>>> ИСПРАВЛЕНО НА: плакать
>>> ВАРИАНТЫ: {'плакать', 'ласкать'}
>>> --------------------
>>> СЛОВО: кнуть
>>> ИСПРАВЛЕНО НА: кнут
>>> ВАРИАНТЫ: {'пнуть', 'ткнуть', 'кнут', 'кинуть'}
>>> --------------------

# если слова не было в словаре, можно добавить его вручную
print("НЕИЗВЕСТНЫЕ СЛОВА:", spell.unknown(["лакать", "интерпретатор"]))
spell.word_frequency.load_words(["лакать", "интерпретатор"])
print("НЕИЗВЕСТНЫЕ СЛОВА:", spell.unknown(["лакать", "интерпретатор"]))
>>> НЕИЗВЕСТНЫЕ СЛОВА: {'лакать', 'интерпретатор'}
>>> НЕИЗВЕСТНЫЕ СЛОВА: set()
>>> --------------------

# так же слова можно загружать просто из текста
print("-"*20)
print("НЕИЗВЕСТНЫЕ СЛОВА:", spell.unknown(["эйлер", "Базеля"]))
spell.word_frequency.load_text("Эйлер (путь которого из Базеля лежал через Любек, Ревель и Кронштадт) прибыл в Санкт-Петербург 24 мая 1727 года")
print("НЕИЗВЕСТНЫЕ СЛОВА:", spell.unknown(["эйлер", "Базеля"]))
>>> НЕИЗВЕСТНЫЕ СЛОВА: {'эйлер', 'базеля'}
>>> НЕИЗВЕСТНЫЕ СЛОВА: set()

# и из файла можно загрузить текст
spell.word_frequency.load_text_file("C:/sometext.txt")

Сразу стоит провести испытания по скорости исправления опечаток для 5000 слов:

import time
import random as rnd
def createBadWords(spell):
    words = []
    for i, word in enumerate(spell.word_frequency.words()):
        if i < 100:
            continue
        if i >= 5100:
            break
        index = rnd.randint(0, len(word))
        char = rnd.choice("абвгдеёжзийклмнопрстуфхцчшщъыьэяю")
        word = word[:index] + char + word[index+1:]
        words.append(word)
    return words       
# протестируем за сколько времени исправятся 5000 слов
words = createBadWords(spell)
st = time.time()
newWords = [spell.correction(word) for word in words]
et = time.time() - st
print(f"ВРЕМЯ НА {len(words)} СЛОВ: {et}")
>>> ВРЕМЯ НА 5000 СЛОВ: 2.9863336086273193

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

mimesis

⭐ github: 3348

Часто для проверки работы алгоритмов нужно собрать достаточно данных, чтобы на них тестировать. Создание данных вручную занимает очень много времени, для избавления от этой рутины может помочь модуль mimesis, который умеет генерировать рандомные данные по нескольким критериям. Устанавливается он просто выполнив: pip install mimesis. При помощи данного модуля можно генерировать различные данные на различных языках, например:

Адресные данные
import mimesis
from mimesis import Address

adrRU = Address(mimesis.locales.RU)
print("Адрес:", adrRU.address())
print("Город:", adrRU.city())
print("Координаты:", adrRU.coordinates())
print("Улица:", adrRU.street_name())
>>> Адрес: ул. Лихоборская 73
>>> Город: Волгореченск
>>> Координаты: {'longitude': -44.258845, 'latitude': 50.719573}
>>> Улица: Украинская

adrRU = Address(mimesis.locales.EN)
print("Адрес:", adrRU.address())
print("Город:", adrRU.city())
print("Координаты:", adrRU.coordinates())
print("Улица:", adrRU.street_name())
>>> Адрес: 858 Navajo Gate
>>> Город: Philadelphia
>>> Координаты: {'longitude': 147.145121, 'latitude': 3.138188}
>>> Улица: Eutaw
Данные, связанные со временем/датой

Большое преимущество этого модуля состоит в том, что данные возвращаются в формате datetime объекта.

import mimesis
from mimesis import Datetime

dt = Datetime(mimesis.locales.RU)
print("Случайная полная дата:", dt.datetime(1998, 2045), type(dt.datetime(1998, 2045)))
print("Случайная дата:", dt.date(1998, 2045), type(dt.date(1998, 2045)))
print("Дата форматированная:", dt.formatted_datetime("%m_%d_%y %H:%M:%S"))
print("День недели:", dt.day_of_week(), dt.day_of_week(abbr=True))
print("Периодичность:", dt.periodicity())
print("Век:", dt.century())

>>> Случайная полная дата: 2029-01-21 01:59:42.671179 <class 'datetime.datetime'>
>>> Случайная дата: 2019-06-11 <class 'datetime.date'>
>>> Дата форматированная: 04_10_06 10:11:03
>>> День недели: Вторник Вт.
>>> Периодичность: Ежедневно
>>> Век: XXI
Данные о человеке
import mimesis
from mimesis import Person

pers = Person(mimesis.locales.RU)

print("Научная степень:", pers.academic_degree())
print("Полное имя мужское:", pers.full_name(mimesis.enums.Gender.MALE))
print("Полное имя женское:", pers.full_name(mimesis.enums.Gender.FEMALE))
print("Национальность:", pers.nationality())
print("Работа:", pers.occupation())
print("Университет:", pers.university())
print("Телефон:", pers.telephone())

>>> Научная степень: Специалист
>>> Полное имя мужское: Намиг Варахобов
>>> Полное имя женское: Солина Гафилова
>>> Национальность: Англичанка
>>> Работа: Бармен
>>> Университет: Государственная морская академия имени адмирала С.О. Макарова
>>> Телефон: +7-(913)-024-20-76

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

Заключение

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

P.S. тестирование библиотек проводилось на Python 3.9 в стандартной IDLE на win 10.

Tags:
Hubs:
Total votes 13: ↑13 and ↓0+13
Comments4

Articles