stdlib2.md
1> **Источник:** https://python-all.ru/3.3/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.3/library/reprlib.html#module-reprlib) предоставляет версию [`repr()`](https://python-all.ru/3.3/library/functions.html#repr), адаптированную для сокращённого отображения больших или глубоко вложенных контейнеров:1415```python16>>> import reprlib17>>> reprlib.repr(set('supercalifragilisticexpialidocious'))18"set(['a', 'c', 'd', 'e', 'f', 'g', ...])"19```2021Модуль [`pprint`](https://python-all.ru/3.3/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.3/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.3/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("%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.3/library/string.html#module-string) включает универсальный класс [`Template`](https://python-all.ru/3.3/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.3/library/string.html#string.Template.substitute) вызывает [``KeyError](https://python-all.ru/3.3/library/exceptions.html#KeyError), когда в словаре или в именованном аргументе отсутствует подстановка. Для приложений типа слияния почты данные, предоставленные пользователем, могут быть неполными, и метод [`safe_substitute()`](https://python-all.ru/3.3/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>>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ')100Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f101102>>> t = BatchRename(fmt)103>>> date = time.strftime('%d%b%y')104>>> for i, filename in enumerate(photofiles):105... base, ext = os.path.splitext(filename)106... newname = t.substitute(d=date, n=i, f=ext)107... print('{0} --> {1}'.format(filename, newname))108109img_1074.jpg --> Ashley_0.jpg110img_1076.jpg --> Ashley_1.jpg111img_1077.jpg --> Ashley_2.jpg112```113114Другое применение шаблонов – отделение логики программы от деталей нескольких выходных форматов. Это позволяет подставлять пользовательские шаблоны для XML-файлов, обычных текстовых отчётов и HTML-отчётов.115116## 11.3. Работа с двоичными структурами данных117118Модуль [`struct`](https://python-all.ru/3.3/library/struct.html#module-struct) предоставляет функции [`pack()`](https://python-all.ru/3.3/library/struct.html#struct.pack) и [`unpack()`](https://python-all.ru/3.3/library/struct.html#struct.unpack) для работы с бинарными записями переменной длины. Следующий пример показывает, как перебирать заголовки в ZIP-файле без использования модуля [`zipfile`](https://python-all.ru/3.3/library/zipfile.html#module-zipfile). Коды упаковки `"H"` и `"I"` представляют двух- и четырёхбайтовые беззнаковые числа соответственно. Маркер `"<"` указывает, что они стандартного размера и имеют порядок байтов от младшего к старшему (little-endian):119120```python121import struct122123with open('myfile.zip', 'rb') as f:124 data = f.read()125126start = 0127for i in range(3): # показать первые 3 заголовка файла128 start += 14129 fields = struct.unpack('<IIIHH', data[start:start+16])130 crc32, comp_size, uncomp_size, filenamesize, extra_size = fields131132 start += 16133 filename = data[start:start+filenamesize]134 start += filenamesize135 extra = data[start:start+extra_size]136 print(filename, hex(crc32), comp_size, uncomp_size)137138 start += extra_size + comp_size # перейти к следующему заголовку139```140141## 11.4. Многопоточность142143Многопоточность – это техника разделения задач, не зависящих последовательно друг от друга. Потоки можно использовать для повышения отзывчивости приложений, принимающих пользовательский ввод, пока другие задачи выполняются в фоне. Смежный случай использования – выполнение операций ввода-вывода параллельно с вычислениями в другом потоке.144145Следующий код показывает, как высокоуровневый модуль [`threading`](https://python-all.ru/3.3/library/threading.html#module-threading) может выполнять задачи в фоне, в то время как основная программа продолжает работу:146147```python148import threading, zipfile149150class AsyncZip(threading.Thread):151 def __init__(self, infile, outfile):152 threading.Thread.__init__(self)153 self.infile = infile154 self.outfile = outfile155 def run(self):156 f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)157 f.write(self.infile)158 f.close()159 print('Finished background zip of:', self.infile)160161background = AsyncZip('mydata.txt', 'myarchive.zip')162background.start()163print('The main program continues to run in foreground.')164165background.join() # Дождаться завершения фоновой задачи166print('Main program waited until background was done.')167```168169Основная сложность многопоточных приложений – координация потоков, которые совместно используют данные или другие ресурсы. Для этого модуль threading предоставляет ряд примитивов синхронизации, включая блокировки, события, условные переменные и семафоры.170171Хотя эти инструменты мощны, небольшие ошибки в проектировании могут привести к проблемам, которые трудно воспроизвести. Поэтому предпочтительным подходом к координации задач является сосредоточение всего доступа к ресурсу в одном потоке и последующее использование модуля [`очередь`](https://python-all.ru/3.3/library/queue.html#module-queue) для подачи в этот поток запросов от других потоков. Приложения, использующие объекты [`Очередь`](https://python-all.ru/3.3/library/queue.html#queue.Queue) для межпотокового взаимодействия и координации, проще в проектировании, более читаемы и надёжны.172173## 11.5. Журналирование174175Модуль [`logging`](https://python-all.ru/3.3/library/logging.html#module-logging) предлагает полнофункциональную и гибкую систему журналирования. В простейшем случае сообщения журнала отправляются в файл или в `sys.stderr`:176177```python178import logging179logging.debug('Debugging information')180logging.info('Informational message')181logging.warning('Warning:config file %s not found', 'server.conf')182logging.error('Error occurred')183logging.critical('Critical error -- shutting down')184```185186Это даёт следующий вывод:187188```text189WARNING:root:Warning:config file server.conf not found190ERROR:root:Error occurred191CRITICAL:root:Critical error -- shutting down192```193194По умолчанию информационные и отладочные сообщения подавляются, а вывод направляется в стандартный поток ошибок. Другие варианты вывода включают маршрутизацию сообщений через электронную почту, датаграммы, сокеты или на HTTP-сервер. Новые фильтры могут выбирать различную маршрутизацию в зависимости от приоритета сообщения: `DEBUG`, `INFO`, `WARNING`, `ERROR`, и `CRITICAL`:195196Система логирования может быть настроена непосредственно из Python или загружена из редактируемого пользователем конфигурационного файла для индивидуальной настройки без изменения приложения.197198## 11.6. Слабые ссылки199200Python выполняет автоматическое управление памятью (подсчёт ссылок для большинства объектов и [*сборка мусора*](https://python-all.ru/3.3/glossary.html#term-garbage-collection) для устранения циклов). Память освобождается вскоре после удаления последней ссылки на неё.201202Этот подход хорошо работает для большинства приложений, но иногда возникает необходимость отслеживать объекты только до тех пор, пока они используются чем-то другим. К сожалению, простое отслеживание создаёт ссылку, которая делает их постоянными. Модуль [`weakref`](https://python-all.ru/3.3/library/weakref.html#module-weakref) предоставляет инструменты для отслеживания объектов без создания ссылки. Когда объект больше не нужен, он автоматически удаляется из таблицы слабых ссылок, и для объектов weakref вызывается колбэк. Типичные применения включают кэширование объектов, создание которых дорого обходится:203204```python205>>> import weakref, gc206>>> class A:207... def __init__(self, value):208... self.value = value209... def __repr__(self):210... return str(self.value)211...212>>> a = A(10) # создать ссылку213>>> d = weakref.WeakValueDictionary()214>>> d['primary'] = a # не создаёт ссылку215>>> d['primary'] # получить объект, если он ещё существует21610217>>> del a # удалить единственную ссылку218>>> gc.collect() # запустить сборку мусора немедленно2190220>>> d['primary'] # запись была автоматически удалена221Traceback (most recent call last):222 File "<stdin>", line 1, in <module>223 d['primary'] # запись была автоматически удалена224 File "C:/python33/lib/weakref.py", line 46, in __getitem__225 o = self.data[key]()226KeyError: 'primary'227```228229## 11.7. Инструменты для работы со списками230231Многие потребности в структурах данных можно удовлетворить с помощью встроенного типа list. Однако иногда возникает необходимость в альтернативных реализациях с другими компромиссами по производительности.232233Модуль [`array`](https://python-all.ru/3.3/library/array.html#module-array) предоставляет объект [`array()`](https://python-all.ru/3.3/library/array.html#array.array), который похож на список, но хранит только однородные данные и делает это более компактно. Следующий пример показывает массив чисел, хранящихся как двухбайтовые беззнаковые двоичные числа (код типа `"H"`) вместо обычных 16 байт на элемент для обычных списков объектов Python int:234235```python236>>> from array import array237>>> a = array('H', [4000, 10, 700, 22222])238>>> sum(a)23926932240>>> a[1:3]241array('H', [10, 700])242```243244Модуль [`collections`](https://python-all.ru/3.3/library/collections.html#module-collections) предоставляет объект [`deque()`](https://python-all.ru/3.3/library/collections.html#collections.deque), который похож на список с более быстрыми добавлениями и извлечениями слева, но более медленным поиском в середине. Эти объекты хорошо подходят для реализации очередей и поиска в ширину в деревьях:245246```python247>>> from collections import deque248>>> d = deque(["task1", "task2", "task3"])249>>> d.append("task4")250>>> print("Handling", d.popleft())251Handling task1252```253254```python255unsearched = deque([starting_node])256def breadth_first_search(unsearched):257 node = unsearched.popleft()258 for m in gen_moves(node):259 if is_goal(m):260 return m261 unsearched.append(m)262```263264В дополнение к альтернативным реализациям списков, библиотека также предлагает другие инструменты, такие как модуль [`bisect`](https://python-all.ru/3.3/library/bisect.html#module-bisect) с функциями для работы с отсортированными списками:265266```python267>>> import bisect268>>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]269>>> bisect.insort(scores, (300, 'ruby'))270>>> scores271[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]272```273274Модуль [`heapq`](https://python-all.ru/3.3/library/heapq.html#module-heapq) предоставляет функции для реализации куч на основе обычных списков. Элемент с наименьшим значением всегда находится на нулевой позиции. Это полезно для приложений, которые многократно обращаются к наименьшему элементу, но не хотят выполнять полную сортировку списка:275276```python277>>> from heapq import heapify, heappop, heappush278>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]279>>> heapify(data) # перестроить список в порядке кучи280>>> heappush(data, -5) # добавить новую запись281>>> [heappop(data) for i in range(3)] # извлечь три наименьших элемента282[-5, 0, 1]283```284285## 11.8. Десятичная арифметика с плавающей запятой286287Модуль [`decimal`](https://python-all.ru/3.3/library/decimal.html#module-decimal) предлагает тип данных [`Decimal`](https://python-all.ru/3.3/library/decimal.html#decimal.Decimal) для арифметики с десятичной плавающей запятой. По сравнению со встроенной реализацией [`float`](https://python-all.ru/3.3/library/functions.html#float) двоичной плавающей запятой, этот класс особенно полезен для288289- финансовых приложений и других случаев, требующих точного десятичного представления,290- контроля точности,291- контроля округления для соблюдения юридических или нормативных требований,292- отслеживания значащих десятичных разрядов, или293- приложений, в которых пользователь ожидает, что результаты будут соответствовать вычислениям, выполненным вручную.294295Например, расчёт налога в 5% на плату за телефон в 70 центов даёт разные результаты в десятичной и двоичной арифметике с плавающей запятой. Разница становится существенной, если результаты округляются до ближайшего цента:296297```python298>>> from decimal import *299>>> round(Decimal('0.70') * Decimal('1.05'), 2)300Decimal('0.74')301>>> round(.70 * 1.05, 2)3020.73303```304305Результат [`Decimal`](https://python-all.ru/3.3/library/decimal.html#decimal.Decimal) сохраняет конечный ноль, автоматически выводя четыре значащие цифры из множителей с двумя значащими цифрами. Decimal воспроизводит математику так, как это делается вручную, и избегает проблем, которые могут возникнуть, когда двоичная плавающая запятая не может точно представить десятичные величины:306307Точное представление позволяет классу [`Decimal`](https://python-all.ru/3.3/library/decimal.html#decimal.Decimal) выполнять вычисления по модулю и проверки на равенство, которые непригодны для двоичной плавающей запятой:308309```python310>>> Decimal('1.00') % Decimal('.10')311Decimal('0.00')312>>> 1.00 % 0.103130.09999999999999995314315>>> sum([Decimal('0.1')]*10) == Decimal('1.0')316True317>>> sum([0.1]*10) == 1.0318False319```320321Модуль [`decimal`](https://python-all.ru/3.3/library/decimal.html#module-decimal) предоставляет арифметику с требуемой точностью:322323```python324>>> getcontext().prec = 36325>>> Decimal(1) / Decimal(7)326Decimal('0.142857142857142857142857142857142857')327```328