20 встроенных библиотек Python, которые заслуживают гораздо большего внимания
Введение
Большинство людей думают, что массовое доминирование Python связано с его мощными библиотеками, такими как NumPy, Pandas, Sklearn, XGBoost и т.д. Это сторонние библиотеки, написанные профессиональными разработчиками, часто с помощью других более быстрых языков программирования, таких как C, Java или C++. .
Таким образом, один из слабых аргументов, которые ненавистники могут привести против Python, заключается в том, что он перестанет быть таким популярным, как только вы избавитесь от всей славы, которую приносят эти сторонние библиотеки. Я здесь, чтобы сказать обратное и показать, что даже стандартный Python достаточно мощен, чтобы составить серьезную конкуренцию любому языку.
Я предлагаю вашему вниманию 20 встроенных библиотек, которые находятся всего в одной строке от того, чтобы быть запущенными.
1️. contextlib
Обработка внешних источников, таких как подключения к базе данных, открытые файлы или всё, что требует ручных операций открытия/закрытия, может стать огромной проблемой. Контекстные менеджеры элегантно решают эту проблему.
Контекстные менеджеры — определяющая функция Python, отсутствующая в других языках и пользующаяся большим спросом. Вы, вероятно, видели ключевое слово with, используемое с функцией open, но вы можете не знать, что можете создавать собственные функции, которые будут работать как контекстные менеджеры.
Ниже вы можете увидеть контекстный менеджер, который служит таймером:
from contextlib import contextmanager
@contextmanager
def timer():
# Start the timer
start = time.time()
# context breakdown
yield
# End the timer
end = time.time()
# Tell the user how much time elapsed
print(f"This code block executed in {round(end - start, 3)} seconds.")
import time
with timer():
for _ in range(10):
time.sleep(0.5)
--------------------------------------------------------------------------
This code block executed in 5.08 seconds.
Обёртывание функции, написанной со специальным синтаксисом, под декоратор contextmanager
из contextlib
, преобразует его в менеджер, который можно использовать с ключевым словом with.
📚 Документация: https://docs.python.org/3/library/contextlib.html
💻 Демо: ссылка
2️. functools
Хотите более мощные, короткие и многофункциональные функции? Тогда вам поможет functools. Эта встроенная библиотека содержит множество методов и декораторов, которые вы можете обернуть существующими, чтобы добавить дополнительные функции.
Одним из них является partial
, который можно использовать для клонирования функций, сохраняя при этом некоторые из их аргументов с пользовательскими значениями. Ниже мы копируем read_csv из Pandas, чтобы нам не приходилось повторять передачу одних и тех же аргументов для чтения некоторых CSV-файлов с похожей структурой:
from functools import partial
import pandas as pd
partial_read_csv = partial(
pd.read_csv, delimiter="|", index_col="date", true_values="true"
)
partial_read_csv("data/specially_formatted.csv")
Ещё одна из моих любимых функций — декоратор кэширования. После переноса кэш запоминает все выходные данные, которые сопоставляются с входными, чтобы результаты были немедленно доступны, когда в функцию передаются одни и те же аргументы. Библиотека Streamlit в значительной степени использует эту функцию.
from functools import cache
@cache # change
def sleep(n):
time.sleep(n)
with timer():
sleep(10)
-------------------------------------------------------------
This code block executed in 10.015 seconds.
with timer():
sleep(10)
---------------------------------------
This code block executed in 0.0 seconds.
📚 Документация: https://docs.python.org/3/library/functools.html
3️. itertools
Если вы когда-нибудь оказывались в ситуации, когда вы пишете вложенные циклы или сложные функции для итерации более чем одного итерируемого объекта, проверьте, есть ли нужная функция в библиотеке itertools. Возможно, вам не придется изобретать велосипед — Python учтёт все ваши потребности.
Ниже приведены некоторые удобные функции итерации из библиотеки:
from itertools import product
a = "ABC"
b = "FGH"
for i in product(a, b):
print(i)
----------------------------------------------------
('A', 'F')
('A', 'G')
('A', 'H')
('B', 'F')
('B', 'G')
('B', 'H')
('C', 'F')
('C', 'G')
('C', 'H')
a = [1, 2, 3, 4]
b = [5, 6]
for item in zip(a, b):
print(item)
(1, 5)
(2, 6)
from itertools import zip_longest
for item in zip_longest(a, b, fillvalue=0):
print(item)
----------------------------------------------------------
(1, 5)
(2, 6)
(3, 0)
(4, 0)
📚 Документация: https://docs.python.org/3/library/itertools.html
4️. glob
Для пользователей, которым нравится сопоставление шаблонов в стиле Unix, библиотека glob
должна чувствовать себя как дома:
import glob
def choose_numbered_files(root="."):
return glob.glob(f"{root}/[0-9].*")
choose_numbered_files("images")
---------------------------------------------------
['images\\1.gif',
'images\\1.png',
'images\\2.gif',
'images\\2.png',
'images\\3.png',
'images\\4.png',
'images\\5.png',
'images\\6.png']
glob
содержит все необходимые функции для работы с несколькими файлами одновременно без головной боли.
📚 Документация: https://docs.python.org/3/library/glob.html
5️. pathlib
Модуль Python os, мягко говоря, отстой… К счастью, разработчики ядра Python услышали крики миллионов и представили библиотеку pathlib в Python 3.4. Она обеспечивает удобный объектно-ориентированный подход к системным путям.
import pathlib
p = pathlib.Path("images")
>>> p.parent
WindowsPath('.')
cwd = pathlib.Path.cwd()
>>> cwd
WindowsPath('C:/Users/User/Desktop/medium_stories/2021/december/4_python_builtins')
Она также очень старается решить все проблемы, связанные с системой путей Windows:
for parent in cwd.parents:
print(parent)
C:\Users\User\Desktop\medium_stories\2021\december
C:\Users\User\Desktop\medium_stories\2021
C:\Users\User\Desktop\medium_stories
C:\Users\User\Desktop
C:\Users\User
C:\Users
C:\
--------------------------------------------------------------
>>> pathlib.Path.home() / "Desktop" / "medium_stories"
WindowsPath('C:/Users/User/Desktop/medium_stories')
📚 Документация: https://docs.python.org/3/library/pathlib.html
6️. sqlite3
К радости специалистов по данным и инженеров, Python поставляется со встроенной поддержкой баз данных и SQL через библиотеку sqlite3. Просто подключитесь к любой базе данных (или создайте её) с помощью объекта подключения и запускайте SQL-запросы.
import sqlite3
con = sqlite3.connect("sample.db")
cursor = con.cursor()
cursor.execute(
"""
CREATE TABLE films
(released text, title text, budget real)
"""
)
con.commit()
con.close()
📚 Документация: https://docs.python.org/3/library/sqlite3.html
7️. hashlib
Python пустил глубокие корни в сфере кибербезопасности, а не только в области искусственного интеллекта и машинного обучения. Примером этого является библиотека hashlib, которая содержит наиболее распространённые (и безопасные) криптографические хеш-функции, такие как SHA256, SHA512 и т. д.
import hashlib
encoded = hashlib.sha256(b"Encode me!")
>>> encoded.hexdigest()
'68907fbd785a694c3617d35a6ce49477ac5704d75f0e727e353da7bc664aacc2'
📚 Документация: https://docs.python.org/3/library/hashlib.html
8️. secrets
Я люблю мистические романы. Вы когда-нибудь читали «Собаку Баскервилей» ? Это фантастика, иди и читай, если ещё этого не сделал!
Хотя реализовать свои собственные функции кодирования сообщений может быть очень весело, они, вероятно, не будут соответствовать тем же стандартам, что и проверенные в боевых условиях функции в библиотеке secrets.
Там вы найдёте всё необходимое для генерации случайных чисел и символов для самых сложных паролей, токенов безопасности и связанных с ними секретов:
import secrets
import string
# From the docs
alphabet = string.ascii_letters + string.digits
password = "".join(secrets.choice(alphabet) for _ in range(10))
>>> password
'VB2ewEtytP'
>>> secrets.token_urlsafe()
'vN4yQy-3T7YE6xzAzw3kZcPMZL1GZUmFpNmlXirAzZA'
>>> secrets.token_hex()
'28dbfdf2897adaa53a91db7808cf4db2be10b0acec95af019dbbaf06ef356e73'
📚 Документация: https://docs.python.org/3/library/secrets.html
9️. argparse
Вы хорошо работаете в командной строке? Тогда вы один из немногих. Также вам понравится библиотека argparse. С её помощью вы можете заставить свои статические сценарии Python принимать пользовательский ввод через аргументы ключевого слова CLI.
Библиотека богата функциональностью, достаточной для создания сложных CLI-приложений для вашего скрипта или даже целых пакетов.
import argparse
parser = argparse.ArgumentParser(
prog="Quadratic equation solver in the form of ax^2 + bx + c = 0",
epilog="Good luck!",
)
parser.add_argument("a", help="The first coefficient")
parser.add_argument("b", help="The second coefficient")
parser.add_argument("c", help="The last coefficient")
args = parser.parse_args()
print(f"The equation is ({args.a}x^2) + ({args.b}x) + ({args.c}) = 0")
-----------------------------------------------------------------------------
$ python example.py 1 -5 6
The equation is (1x^2) + (-5x) + (6) = 0
📚 Документация: https://docs.python.org/3/library/argparse.html
💻 Демо-руководство: Настоящий Python
10. random
В этом мире не бывает случайностей — Угвэй.
Может быть, поэтому учёные используют псевдослучайность, что чистой случайности не существует. (Не правда)
В любом случае, модуля random в Python должно быть более чем достаточно для имитации основных случайных событий:
import random
normal_dist = random.gauss(0, 1)
>>> normal_dist
-1.1497306720936395
>>> random.choice(list(range(1000)))
444
unordered = list(range(10))
random.shuffle(unordered)
>>> unordered
[1, 6, 5, 4, 0, 8, 2, 7, 3, 9]
📚 Документация: https://docs.python.org/3/library/random.html
1️1. pickle
Точно так же, как размеры наборов данных становятся всё больше и больше, растут и наши потребности в их более быстром и эффективном хранении. Одной из альтернатив плоским CSV-файлам, которые поставляются с вашей установкой Python, является формат файла pickle. На самом деле он примерно в 80 раз быстрее CSV при вводе-выводе и занимает меньше памяти.
Вот пример, который собирает набор данных и загружает его обратно:
import pickle
import seaborn as sns
df = sns.load_dataset("diamonds")
with open("data/diamonds.pkl", "wb") as file:
pickle.dump(df, file)
with open("data/diamonds.pkl", "rb") as file:
df_loaded = pickle.load(file)
df_loaded.head()
📚 Документация: https://docs.python.org/3/library/pickle.html
💻 Сравнительная статья Дарио Радечича: ссылка
1️2. shutil
Библиотека Shutil, обозначающая утилиты оболочки, представляет собой модуль для расширенных операций с файлами. С помощью Shutil вы можете копировать, перемещать, удалять, архивировать или выполнять любые операции с файлами, которые вы обычно выполняете в проводнике или в терминале:
import shutil
>>> dir(shutil)
[
'copy',
'make_archive',
'move',
'nt',
'os',
'posix',
'register_archive_format',
'register_unpack_format',
'rmtree',
'stat',
'sys',
'which']
>>> shutil.which("conda")
'C:\\Users\\User\\anaconda3\\Library\\bin\\conda.BAT'
>>> shutil.move("data/diamonds.pkl", "data/pickles/diamonds.pkl")
'data/pickles/diamonds.pkl'
📚 Документация: https://docs.python.org/3/library/shutil.html
13. statistics
Кому вообще нужны NumPy или SciPy, когда есть модуль statistics
? (Вообще-то все так делают — я просто хотел написать драматическую фразу).
Этот модуль может пригодиться для выполнения стандартных статистических вычислений на чистых массивах Python. Нет необходимости устанавливать сторонние пакеты, если всё, что вам нужно, это сделать простой расчёт.
import statistics
array = [random.randint(1, 1000) for _ in range(1000)]
array2 = [random.randint(1, 1000) for _ in range(1000)]
>>> statistics.mean(array)
508.506
>>> statistics.stdev(array2)
285.835948210314
>>> statistics.quantiles(array2, n=10)
[103.2, 199.6, 323.3, 412.2, 512.5, 601.0, 696.0, 789.0, 900.9]
📚Документация: https://docs.python.org/3/library/statistics.html
14. gc
Python действительно делает всё возможное. Он поставляется со всем — от менеджеров пакетов до сборщиков мусора.
Да, вы меня правильно поняли. После включения модуль gc служит сборщиком мусора в программах на Python. В языках более низкого уровня эта утомительная задача возлагается на разработчика, который должен вручную выделять и освобождать блоки памяти, необходимые в программе.
import gc
>>> gc.enable()
>>> gc.collect()
44
Функция collect
возвращает количество недоступных объектов, найденных в пространстве имён, и удаляет их. Проще говоря, функция освобождает слот памяти неиспользуемых объектов. Вы можете прочитать больше об управлении памятью в Python ниже.
📚Документация: https://docs.python.org/3/library/gc.html
💻Управление памятью в Python — ссылка
15. pprint
Некоторые результаты определённых операций просто ужасны, чтобы на них смотреть. Сделайте своим глазам одолжение и используйте библиотеку pprint
для интеллектуальных отступов и красивого вывода:
nested = [list("abcs"), list("sdff"), [1, 45, 4, 6, 7, 8], list(range(12))]
>>> print(nested)
[['a', 'b', 'c', 's'], ['s', 'd', 'f', 'f'], [1, 45, 4, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
from pprint import pprint
>>> pprint(nested)
[['a', 'b', 'c', 's'],
['s', 'd', 'f', 'f'],
[1, 45, 4, 6, 7, 8],
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
Для ещё более сложных выводов и пользовательских параметров вывода вы можете создавать объекты принтеров с помощью pprint
и использовать их несколько раз. Подробности в документации ниже.
📚 Документация: https://docs.python.org/3/library/pprint.html
16. pydoc
Код чаще читают, чем пишут — Гвидо Ван Россум.
Угадай, что? Я люблю документацию и пишу её для собственного кода (не удивляйтесь, у меня немного обсессивно-компульсивное расстройство).
Ненавижу это или люблю — документирование кода — неизбежное зло. Это становится существенно важным для более крупных проектов. В таких случаях можно использовать библиотеку CLI pydoc для автоматического создания документации в браузере или сохранить их в HTML, используя строки документации ваших классов и функций.
Она может служить предварительным обзорным инструментом перед развёртыванием ваших документаций в других службах, таких как Read the Docs.
📚Документация: https://docs.python.org/3/library/pydoc.html
💻 Руководство по документированию кода — Real Python
17. calendar
Что, чёрт возьми, происходило в сентябре 1752 года?
Судя по всему, в сентябре 1752 года в Великобритании было 19 дней. Куда делись 3, 4, … 13? Ну, а все дело в гигантской путанице с переходом с юлианского календаря на григорианский, в отношении которого Великобритания упорствовала до 1750-х годов.
Так было только в Великобритании. Остальной мир имел смысл и следовал правильному течению времени, что можно увидеть с помощью модуля calendar:
import calendar
>>> print(calendar.month(1752, 9))
September 1752
Mo Tu We Th Fr Sa Su
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
Python серьёзно относится ко времени.
# Return number of leap days within a range
>>> calendar.leapdays(1, 2022)
490
📚Документация: https://docs.python.org/3/library/calendar.html
18. webbrowser
Представьте, что вы сразу переходите к StackOverflow из блокнота Jupyter или скрипта Python. Зачем тебе вообще это делать?
Ну, потому что вы МОЖЕТЕ… с модулем
.webbrowser
📚Документация: https://docs.python.org/3/library/webbrowser.html
19. logging
Одним из признаков того, что вы смотрите на опытного разработчика, является отсутствие операторов печати в их коде. Ванильная функция печати не просто урежет её для множества вариантов использования, с которыми вам приходится иметь дело при кодировании и отладке. Вам нужно использовать более сложные инструменты, такие как логирование.
Этот модуль позволяет регистрировать сообщения с различными приоритетами и временными метками в пользовательском формате. Вот тот, который я использую ежедневно:
import logging
# Set the log format
logging.basicConfig(
format="%(asctime)s - %(message)s", datefmt="%d-%b-%y %H:%M:%S", level=logging.INFO
)
>>> logging.info("Finished execution")
31-Dec-21 20:26:30 - Finished execution
>>> logging.critical("Critical error!")
31-Dec-21 20:26:30 - Critical error!
📚 Документация: https://docs.python.org/3/library/logging.html
💻 Отличный туториал по логированию в Python: Real Python
20. concurrent.futures
Я оставил что-то пикантное на конец статьи. Эта библиотека предназначена для одновременного выполнения операций, как в многопоточности.
Ниже я отправляю 100 запросов GET на URL-адрес и получаю ответ. Процесс медленный и утомительный, так как интерпретатор ждёт, пока не вернется каждый запрос, и это то, что вы получаете, когда используете циклы.
import requests
URL = "https://www.google.com/"
def get(url: str):
response = requests.get(url)
return response.content
with timer():
for index, _ in enumerate(range(101), 1):
get(URL)
------------------------------------------------------------
This code block executed in 106.313 seconds.
Гораздо разумнее использовать параллелизм и задействовать все ядра на вашем компьютере. Библиотека concurrent.futures
позволяет это сделать. Вот основной синтаксис:
import concurrent.futures as cf
# Initiate a timer
with timer():
# Initiate a pool
with cf.ThreadPoolExecutor() as tpe:
for index, _ in enumerate(range(100), 1):
tpe.submit(get, URL)
This code block executed in 7.929 seconds.
Время выполнения сократилось в 12 раз, так как параллелизм позволял отправлять несколько запросов одновременно, используя все ядра. Вы можете узнать больше о параллелизме в приведённом ниже руководстве.
📚 Документация: https://docs.python.org/3/library/concurrent.futures.html
💻 Демо-руководство: статья Дарио Радечича
Заключение
Нет необходимости чрезмерно усложнять вещи. Если они вам не нужны, нет необходимости загружать вашу виртуальную среду тяжелыми пакетами. Достаточно иметь несколько встроенных пакетов в рукаве.