stdlib2.md
1> **Источник:** https://python-all.ru/3.13/tutorial/stdlib2.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 11. Краткий обзор стандартной библиотеки – часть II89Этот второй обзор охватывает более продвинутые модули, поддерживающие потребности профессионального программирования. Такие модули редко встречаются в небольших скриптах.1011## 11.1. Форматирование вывода1213Модуль [`reprlib`](https://python-all.ru/3.13/library/reprlib.html#module-reprlib) предоставляет версию [`repr()`](https://python-all.ru/3.13/library/functions.html#repr), настроенную для сокращённого отображения больших или глубоко вложенных контейнеров:1415```python16>>> import reprlib17>>> reprlib.repr(set('supercalifragilisticexpialidocious'))18"{'a', 'c', 'd', 'e', 'f', 'g', ...}"19```2021Модуль [`pprint`](https://python-all.ru/3.13/library/pprint.html#module-pprint) обеспечивает более тонкий контроль над выводом как встроенных, так и пользовательских объектов в удобном для интерпретатора виде. Когда результат длиннее одной строки, «pretty printer» добавляет разрывы строк и отступы, чтобы чётче показать структуру данных:2223```python24>>> import pprint25>>> t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta',26... 'yellow'], 'blue']]]27...28>>> pprint.pprint(t, width=30)29[[[['black', 'cyan'],30 'white',31 ['green', 'red']],32 [['magenta', 'yellow'],33 'blue']]]34```3536Модуль [`textwrap`](https://python-all.ru/3.13/library/textwrap.html#module-textwrap) форматирует абзацы текста под заданную ширину экрана:3738```python39>>> import textwrap40>>> doc = """The wrap() method is just like fill() except that it returns41... a list of strings instead of one big string with newlines to separate42... the wrapped lines."""43...44>>> print(textwrap.fill(doc, width=40))45The wrap() method is just like fill()46except that it returns a list of strings47instead of one big string with newlines48to separate the wrapped lines.49```5051Модуль [`locale`](https://python-all.ru/3.13/library/locale.html#module-locale) обращается к базе данных форматов данных, зависящих от культурных особенностей. Атрибут grouping функции format модуля locale предоставляет прямой способ форматирования чисел с разделителями групп:5253```python54>>> import locale55>>> locale.setlocale(locale.LC_ALL, 'English_United States.1252')56'English_United States.1252'57>>> conv = locale.localeconv() # получить отображение соглашений58>>> x = 1234567.859>>> locale.format_string("%d", x, grouping=True)60'1,234,567'61>>> locale.format_string("%s%.*f", (conv['currency_symbol'],62... conv['frac_digits'], x), grouping=True)63'$1,234,567.80'64```6566## 11.2. Шаблоны6768Модуль [`string`](https://python-all.ru/3.13/library/string.html#module-string) включает универсальный класс [`Template`](https://python-all.ru/3.13/library/string.html#string.Template) с упрощённым синтаксисом, подходящим для редактирования конечными пользователями. Это позволяет пользователям настраивать свои приложения без необходимости изменять само приложение.6970Формат использует имена-заполнители, образованные `$` с допустимыми идентификаторами Python (буквенно-цифровые символы и подчёркивания). Заключение заполнителя в фигурные скобки позволяет сразу за ним следовать дополнительным буквенно-цифровым символам без пробелов. Написание `$$` создаёт один экранированный `$`:7172```python73>>> from string import Template74>>> t = Template('${village}folk send $$10 to $cause.')75>>> t.substitute(village='Nottingham', cause='the ditch fund')76'Nottinghamfolk send $10 to the ditch fund.'77```7879Метод [`substitute()`](https://python-all.ru/3.13/library/string.html#string.Template.substitute) возбуждает исключение [`KeyError`](https://python-all.ru/3.13/library/exceptions.html#KeyError), если заполнитель не передан ни как ключ словаря, ни как именованный аргумент. Для приложений типа слияния писем (mail-merge) пользовательские данные могут быть неполными, и метод [`safe_substitute()`](https://python-all.ru/3.13/library/string.html#string.Template.safe_substitute) может оказаться более подходящим – он оставляет заполнители без изменений, если данные отсутствуют:8081```python82>>> t = Template('Return the $item to $owner.')83>>> d = dict(item='unladen swallow')84>>> t.substitute(d)85Traceback (most recent call last):86 ...87KeyError: 'owner'88>>> t.safe_substitute(d)89'Return the unladen swallow to $owner.'90```9192Подклассы Template могут задавать собственный разделитель. Например, утилита пакетного переименования для просмотра фотографий может использовать знаки процента для заполнителей, таких как текущая дата, номер изображения по порядку или формат файла:9394```python95>>> import time, os.path96>>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']97>>> class BatchRename(Template):98... delimiter = '%'99...100>>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ')101Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f102103>>> t = BatchRename(fmt)104>>> date = time.strftime('%d%b%y')105>>> for i, filename in enumerate(photofiles):106... base, ext = os.path.splitext(filename)107... newname = t.substitute(d=date, n=i, f=ext)108... print('{0} --> {1}'.format(filename, newname))109110img_1074.jpg --> Ashley_0.jpg111img_1076.jpg --> Ashley_1.jpg112img_1077.jpg --> Ashley_2.jpg113```114115Другое применение шаблонов – отделение логики программы от деталей нескольких выходных форматов. Это позволяет подставлять пользовательские шаблоны для XML-файлов, обычных текстовых отчётов и HTML-отчётов.116117## 11.3. Работа с бинарными форматами записей118119Модуль [`struct`](https://python-all.ru/3.13/library/struct.html#module-struct) предоставляет функции [`pack()`](https://python-all.ru/3.13/library/struct.html#struct.pack) и [`unpack()`](https://python-all.ru/3.13/library/struct.html#struct.unpack) для работы с бинарными форматами записей переменной длины. Следующий пример показывает, как перебрать информацию заголовка в ZIP-файле без использования модуля [`zipfile`](https://python-all.ru/3.13/library/zipfile.html#module-zipfile). Упаковочные коды `"H"` и `"I"` представляют двух- и четырёхбайтовые беззнаковые числа соответственно. `"<"` указывает, что они стандартного размера и в порядке байтов little-endian:120121```python122import struct123124with open('myfile.zip', 'rb') as f:125 data = f.read()126127start = 0128for i in range(3): # показать первые 3 заголовка файла129 start += 14130 fields = struct.unpack('<IIIHH', data[start:start+16])131 crc32, comp_size, uncomp_size, filenamesize, extra_size = fields132133 start += 16134 filename = data[start:start+filenamesize]135 start += filenamesize136 extra = data[start:start+extra_size]137 print(filename, hex(crc32), comp_size, uncomp_size)138139 start += extra_size + comp_size # перейти к следующему заголовку140```141142## 11.4. Многопоточность143144Многопоточность – это техника разделения задач, не зависящих последовательно друг от друга. Потоки можно использовать для повышения отзывчивости приложений, принимающих пользовательский ввод, пока другие задачи выполняются в фоне. Смежный случай использования – выполнение операций ввода-вывода параллельно с вычислениями в другом потоке.145146Следующий код показывает, как высокоуровневый модуль [`threading`](https://python-all.ru/3.13/library/threading.html#module-threading) может выполнять задачи в фоне, пока основная программа продолжает работу:147148```python149import threading, zipfile150151class AsyncZip(threading.Thread):152 def __init__(self, infile, outfile):153 super().__init__()154 self.infile = infile155 self.outfile = outfile156157 def run(self):158 with zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED) as f:159 f.write(self.infile)160 print('Finished background zip of:', self.infile)161162background = AsyncZip('mydata.txt', 'myarchive.zip')163background.start()164print('The main program continues to run in foreground.')165166background.join() # Дождаться завершения фоновой задачи167print('Main program waited until background was done.')168```169170Основная сложность многопоточных приложений – координация потоков, которые совместно используют данные или другие ресурсы. Для этого модуль threading предоставляет ряд примитивов синхронизации, включая блокировки, события, условные переменные и семафоры.171172Хотя эти инструменты мощные, небольшие ошибки проектирования могут привести к проблемам, которые трудно воспроизвести. Поэтому предпочтительный подход к координации задач – сосредоточить весь доступ к ресурсу в одном потоке, а затем использовать модуль [`queue`](https://python-all.ru/3.13/library/queue.html#module-queue) для подачи запросов от других потоков в этот поток. Приложения, использующие объекты [`Queue`](https://python-all.ru/3.13/library/queue.html#queue.Queue) для межпоточной связи и координации, проще в проектировании, более читаемы и надёжны.173174## 11.5. Логирование175176Модуль [`logging`](https://python-all.ru/3.13/library/logging.html#module-logging) предлагает полнофункциональную и гибкую систему логирования. В самом простом случае сообщения журнала отправляются в файл или на `sys.stderr`:177178```python179import logging180logging.debug('Debugging information')181logging.info('Informational message')182logging.warning('Warning:config file %s not found', 'server.conf')183logging.error('Error occurred')184logging.critical('Critical error -- shutting down')185```186187Это даёт следующий вывод:188189```text190WARNING:root:Warning:config file server.conf not found191ERROR:root:Error occurred192CRITICAL:root:Critical error -- shutting down193```194195По умолчанию информационные и отладочные сообщения подавляются, а вывод направляется в стандартный поток ошибок. Другие варианты вывода включают маршрутизацию сообщений через электронную почту, дейтаграммы, сокеты или HTTP-сервер. Новые фильтры могут выбирать разную маршрутизацию в зависимости от приоритета сообщения: [`DEBUG`](https://python-all.ru/3.13/library/logging.html#logging.DEBUG), [`INFO`](https://python-all.ru/3.13/library/logging.html#logging.INFO), [`WARNING`](https://python-all.ru/3.13/library/logging.html#logging.WARNING), [`ERROR`](https://python-all.ru/3.13/library/logging.html#logging.ERROR) и [`CRITICAL`](https://python-all.ru/3.13/library/logging.html#logging.CRITICAL).196197Система логирования может быть настроена непосредственно из Python или загружена из редактируемого пользователем конфигурационного файла для индивидуальной настройки без изменения приложения.198199## 11.6. Слабые ссылки200201Python выполняет автоматическое управление памятью (подсчёт ссылок для большинства объектов и [сборка мусора](https://python-all.ru/3.13/glossary.html#term-garbage-collection) для устранения циклов). Память освобождается вскоре после удаления последней ссылки на неё.202203Такой подход отлично работает для большинства приложений, но иногда возникает необходимость отслеживать объекты только до тех пор, пока они используются чем-то ещё. К сожалению, само отслеживание создаёт ссылку, делающую объект постоянным. Модуль [`weakref`](https://python-all.ru/3.13/library/weakref.html#module-weakref) предоставляет инструменты для отслеживания объектов без создания ссылки. Когда объект больше не нужен, он автоматически удаляется из таблицы слабых ссылок, и для объектов weakref вызывается колбэк. Типичные применения включают кэширование объектов, создание которых дорого:204205```python206>>> import weakref, gc207>>> class A:208... def __init__(self, value):209... self.value = value210... def __repr__(self):211... return str(self.value)212...213>>> a = A(10) # создать ссылку214>>> d = weakref.WeakValueDictionary()215>>> d['primary'] = a # не создаёт ссылку216>>> d['primary'] # получить объект, если он ещё существует21710218>>> del a # удалить единственную ссылку219>>> gc.collect() # запустить сборку мусора немедленно2200221>>> d['primary'] # запись была автоматически удалена222Traceback (most recent call last):223 File "<stdin>", line 1, in <module>224 d['primary'] # запись была автоматически удалена225 File "C:/python313/lib/weakref.py", line 46, in __getitem__226 o = self.data[key]()227KeyError: 'primary'228```229230## 11.7. Инструменты для работы со списками231232Многие потребности в структурах данных можно удовлетворить с помощью встроенного типа list. Однако иногда возникает необходимость в альтернативных реализациях с другими компромиссами по производительности.233234Модуль [`array`](https://python-all.ru/3.13/library/array.html#module-array) предоставляет объект [`array`](https://python-all.ru/3.13/library/array.html#array.array), который подобен списку, но хранит только однородные данные и делает это более компактно. Следующий пример показывает массив чисел, хранящихся в виде двухбайтовых беззнаковых двоичных чисел (код типа `"H"`) вместо обычных 16 байтов на элемент для обычных списков объектов Python int:235236```python237>>> from array import array238>>> a = array('H', [4000, 10, 700, 22222])239>>> sum(a)24026932241>>> a[1:3]242array('H', [10, 700])243```244245Модуль [`collections`](https://python-all.ru/3.13/library/collections.html#module-collections) предоставляет объект [`deque`](https://python-all.ru/3.13/library/collections.html#collections.deque), который подобен списку, но с более быстрым добавлением и извлечением элементов слева и более медленным поиском в середине. Эти объекты хорошо подходят для реализации очередей и поиска в ширину по дереву:246247```python248>>> from collections import deque249>>> d = deque(["task1", "task2", "task3"])250>>> d.append("task4")251>>> print("Handling", d.popleft())252Handling task1253```254255```python256unsearched = deque([starting_node])257def breadth_first_search(unsearched):258 node = unsearched.popleft()259 for m in gen_moves(node):260 if is_goal(m):261 return m262 unsearched.append(m)263```264265В дополнение к альтернативным реализациям списков, библиотека также предлагает другие инструменты, такие как модуль [`bisect`](https://python-all.ru/3.13/library/bisect.html#module-bisect) с функциями для работы с отсортированными списками:266267```python268>>> import bisect269>>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]270>>> bisect.insort(scores, (300, 'ruby'))271>>> scores272[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]273```274275Модуль [`heapq`](https://python-all.ru/3.13/library/heapq.html#module-heapq) предоставляет функции для реализации куч на основе обычных списков. Запись с наименьшим значением всегда хранится в позиции ноль. Это полезно для приложений, которые многократно обращаются к наименьшему элементу, но не хотят выполнять полную сортировку списка:276277```python278>>> from heapq import heapify, heappop, heappush279>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]280>>> heapify(data) # перестроить список в порядке кучи281>>> heappush(data, -5) # добавить новую запись282>>> [heappop(data) for i in range(3)] # извлечь три наименьших элемента283[-5, 0, 1]284```285286## 11.8. Десятичная арифметика с плавающей запятой287288Модуль [`decimal`](https://python-all.ru/3.13/library/decimal.html#module-decimal) предлагает тип данных [`Decimal`](https://python-all.ru/3.13/library/decimal.html#decimal.Decimal) для десятичной арифметики с плавающей запятой. По сравнению со встроенной реализацией [`float`](https://python-all.ru/3.13/library/functions.html#float) двоичной арифметики с плавающей запятой, этот класс особенно полезен для289290- финансовых приложений и других случаев, требующих точного десятичного представления,291- контроля точности,292- контроля округления для соблюдения юридических или нормативных требований,293- отслеживания значащих десятичных разрядов, или294- приложений, в которых пользователь ожидает, что результаты будут соответствовать вычислениям, выполненным вручную.295296Например, расчёт налога в 5% на плату за телефон в 70 центов даёт разные результаты в десятичной и двоичной арифметике с плавающей запятой. Разница становится существенной, если результаты округляются до ближайшего цента:297298```python299>>> from decimal import *300>>> round(Decimal('0.70') * Decimal('1.05'), 2)301Decimal('0.74')302>>> round(.70 * 1.05, 2)3030.73304```305306Результат [`Decimal`](https://python-all.ru/3.13/library/decimal.html#decimal.Decimal) сохраняет конечный ноль, автоматически определяя четырёхзначную точность из сомножителей с двузначной точностью. Decimal воспроизводит математику так, как это делается вручную, и позволяет избежать проблем, возникающих, когда двоичная арифметика с плавающей запятой не может точно представить десятичные величины.307308Точное представление позволяет классу [`Decimal`](https://python-all.ru/3.13/library/decimal.html#decimal.Decimal) выполнять вычисления по модулю и проверки равенства, которые непригодны для двоичной арифметики с плавающей запятой:309310```python311>>> Decimal('1.00') % Decimal('.10')312Decimal('0.00')313>>> 1.00 % 0.103140.09999999999999995315316>>> sum([Decimal('0.1')]*10) == Decimal('1.0')317True318>>> 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 == 1.0319False320```321322Модуль [`decimal`](https://python-all.ru/3.13/library/decimal.html#module-decimal) предоставляет арифметику с любой необходимой точностью:323324```python325>>> getcontext().prec = 36326>>> Decimal(1) / Decimal(7)327Decimal('0.142857142857142857142857142857142857')328```329