10. Краткий обзор стандартной библиотеки
****************************************


10.1. Интерфейс операционной системы
====================================

Модуль "os" предоставляет десятки функций для взаимодействия с
операционной системой:

   >>> import os
   >>> os.getcwd()      # Return the current working directory
   'C:\\Python316'
   >>> os.chdir('/server/accesslogs')   # Change current working directory
   >>> os.system('mkdir today')   # Run the command mkdir in the system shell
   0

Для импорта этого модуля используйте стиль "import os", а не "from os
import *". В противном случае "os.open()" затенит встроенную функцию
"open()", а они работают по-разному.

Встроенные функции "dir()" и "help()" полезны как интерактивные
помощники при работе с большими модулями, вроде "os":

   >>> import os
   >>> dir(os)
   <возвращает список всех функций модуля>
   >>> help(os)
   <возвращает подробную справку, собранную из docstring’ов модуля>

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

   >>> import shutil
   >>> shutil.copyfile('data.db', 'archive.db')
   'archive.db'
   >>> shutil.move('/build/executables', 'installdir')
   'installdir'


10.2. Шаблоны файлов
====================

Модуль "glob" предоставляет функцию для получения списка файлов по
указанному шаблону:

   >>> import glob
   >>> glob.glob('*.py')
   ['primes.py', 'random.py', 'quote.py']


10.3. Аргументы командной строки
================================

Обычным служебным скриптам часто приходится обрабатывать аргументы
командной строки. Эти аргументы хранятся в атрибуте *argv* модуля
"sys" в виде списка. Например, рассмотрим следующий файл "demo.py":

   # Файл demo.py
   import sys
   print(sys.argv)

Вот результат выполнения "python demo.py one two three" в командной
строке:

   ['demo.py', 'one', 'two', 'three']

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

   import argparse

   parser = argparse.ArgumentParser(
       prog='top',
       description='Показать верхние строки из каждого файла')
   parser.add_argument('filenames', nargs='+')
   parser.add_argument('-l', '--lines', type=int, default=10)
   args = parser.parse_args()
   print(args)

При запуске из командной строки как "python top.py --lines=5 alpha.txt
beta.txt", скрипт установит "args.lines" в "5", а "args.filenames" в
"['alpha.txt', 'beta.txt']".


10.4. Перенаправление вывода ошибок и завершение программы
==========================================================

Модуль "sys" содержит также атрибуты *stdin*, *stdout* и *stderr*.
Последний полезен для вывода предупреждений и сообщений об ошибках,
которые должны быть видны даже при перенаправленном *stdout*:

   >>> sys.stderr.write('Предупреждение, файл журнала не найден — начинаю новый\n')
   Предупреждение, файл журнала не найден — начинаю новый

Самый простой способ завершить программу -- вызвать "sys.exit()".


10.5. Сопоставление строк с шаблонами
=====================================

Модуль "re" предоставляет инструменты регулярных выражений для
продвинутой обработки строк. Для сложного сопоставления и
преобразования регулярные выражения предлагают лаконичные и
оптимизированные решения:

   >>> import re
   >>> re.findall(r'\bп[а-я]*', 'прыгнул кот или пушистый попугай')
   ['прыгнул', 'пушистый', 'попугай']
   >>> re.sub(r'(\b[а-я]+) \1', r'\1', 'кот на на крыше')
   'кот на крыше'

Если нужны только простые возможности, методы строк предпочтительнее,
потому что их проще читать и отлаживать:

   >>> 'чай для два'.replace('два', 'двоих')
   'чай для двоих'


10.6. Математика
================

Модуль "math" даёт доступ к функциям стандартной библиотеки C для
вычислений с плавающей точкой:

   >>> import math
   >>> math.cos(math.pi / 4)
   0.70710678118654757
   >>> math.log(1024, 2)
   10.0

Модуль "random" предоставляет инструменты для выполнения случайных
выборок:

   >>> import random
   >>> random.choice(['яблоко', 'груша', 'банан'])
   'яблоко'
   >>> random.sample(range(100), 10)   # выборка без повторов
   [30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
   >>> random.random()    # случайное число с плавающей точкой из интервала [0.0, 1.0)
   0.17970987693706186
   >>> random.randrange(6)    # случайное целое из диапазона range(6)
   4

Модуль "statistics" позволяет вычислять базовые статистические
характеристики (среднее, медиану, дисперсию и т. п.) для числовых
данных:

   >>> import statistics
   >>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
   >>> statistics.mean(data)
   1.6071428571428572
   >>> statistics.median(data)
   1.25
   >>> statistics.variance(data)
   1.3720238095238095

Проект SciPy <https://scipy.org> содержит большое количество других
модулей для численных вычислений.


10.7. Доступ в интернет
=======================

Есть множество модулей, предназначенных для доступа в интернет и
работы с его протоколами. Два самых простых модуля: "urllib.request" —
для получения данных по URL и "smtplib" — для отправки электронной
почты:

   >>> from urllib.request import urlopen
   >>> with urlopen('https://docs.python.org/3/') as response:
   ...     for line in response:
   ...         line = line.decode()             # Преобразовать байты в строку
   ...         if 'updated' in line:
   ...             print(line.rstrip())         # Убрать завершающий перевод строки
   ...
         Last updated on Nov 11, 2025 (20:11 UTC).

   >>> import smtplib
   >>> server = smtplib.SMTP('localhost')
   >>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
   ... """To: jcaesar@example.org
   ... From: soothsayer@example.org
   ...
   ... Остерегайся мартовских ид.
   ... """)
   >>> server.quit()

(Обратите внимание, что для второго примера требуется почтовый сервер,
запущенный на localhost.)


10.8. Дата и время
==================

Модуль "datetime" предоставляет классы для манипуляции с датами и
временем как простыми, так и сложными способами. Хотя поддерживается
арифметика дат и времени, основное внимание в реализации уделяется
эффективному извлечению элементов для форматирования и обработки
выходных данных. Модуль также поддерживает объекты, учитывающие
часовой пояс.

   >>> # даты легко создавать и форматировать
    >>> import datetime as dt
   >>> now = dt.date.today()
   >>> now
   datetime.date(2003, 12, 2)
   >>> now.strftime("%d.%m.%y. Сегодня %A. %B %Y-го года идёт уже %-d-й день.")
   '02.12.03. Сегодня Вторник. Декабрь 2003-го года идёт уже 2-й день.'

   >>> # даты поддерживают календарную арифметику
   >>> birthday = date(1964, 7, 31)
   >>> age = now - birthday
   >>> age.days
   14368


10.9. Сжатие данных
===================

Распространённые форматы архивирования и сжатия данных напрямую
поддерживаются модулями, включая "zlib", "gzip", "bz2", "lzma",
"zipfile" и "tarfile".

   >>> import zlib
   >>> s = b'witch which has which witches wrist watch'
   >>> len(s)
   41
   >>> t = zlib.compress(s)
   >>> len(t)
   37
   >>> zlib.decompress(t)
   b'witch which has which witches wrist watch'
   >>> zlib.crc32(s)
   226805979


10.10. Измерение производительности
===================================

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

Например, может быть заманчивым использовать распаковку и упаковку
кортежей вместо традиционного подхода к обмену значений между
переменными. Модуль "timeit" быстро показывает скромное преимущество в
производительности:

   >>> from timeit import Timer
   >>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
   0.57535828626024577
   >>> Timer('a,b = b,a', 'a=1; b=2').timeit()
   0.54962537085770791

В отличие от высокой детализации "timeit", модули "profile" и "pstats"
предоставляют инструменты для выявления критичных по времени участков
в более крупных блоках кода.


10.11. Контроль качества
========================

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

Модуль "doctest" предоставляет инструмент для сканирования модуля и
проверки тестов, встроенных в строки документации программы. Создание
теста настолько просто, что достаточно скопировать типичный вызов
функции вместе с результатом в строку документации. Это улучшает
документацию, предоставляя пользователю пример, и позволяет модулю
doctest убедиться, что код соответствует документации.

   def average(values):
       """Вычисляет среднее арифметическое списка чисел.

       >>> print(average([20, 30, 70]))
       40.0
       """
       return sum(values) / len(values)

   import doctest
   doctest.testmod()   # автоматически проверяет встроенные тесты

Модуль "unittest" не так просто в использовании, как "doctest", но
позволяет поддерживать более полный набор тестов в отдельном файле:

   import unittest

   class TestStatisticalFunctions(unittest.TestCase):

       def test_average(self):
           self.assertEqual(average([20, 30, 70]), 40.0)
           self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
           with self.assertRaises(ZeroDivisionError):
               average([])
           with self.assertRaises(TypeError):
               average(20, 30, 70)

   unittest.main()  # Запуск с командной строки вызывает все тесты


10.12. Батарейки прилагаются
============================

Python придерживается философии «батарейки включены в комплект». Это
лучше всего проявляется в продвинутых и надёжных возможностях его
крупных пакетов. Например:

* Модули "xmlrpc.client" и "xmlrpc.server" делают реализацию
  удалённого вызова процедур почти тривиальной задачей. Несмотря на
  название модулей, не требуется прямых знаний или обработки XML.

* Пакет "email" — библиотека для управления сообщениями электронной
  почты, включая MIME и другие документы сообщений, основанные на
  **RFC 5322**. В отличие от модулей "smtplib" и "poplib", которые
  предназначены именно для отправки и получения сообщений, в пакете
  email содержится полный набор инструментов для создания и
  декодирования сообщений со сложной структурой (включая вложения), а
  также для работы с интернет-кодировками и заголовками.

* Пакет "json" предоставляет надёжные средства для работы с этим
  популярным форматом обмена данными. Модуль "csv" поддерживает прямое
  чтение и запись файлов в формате CSV (Comma-Separated Value), широко
  используемом в базах данных и электронных таблицах. Обработка XML
  осуществляется пакетами "xml.etree.ElementTree", "xml.dom" и
  "xml.sax". Вместе эти модули и пакеты значительно упрощают обмен
  данными между приложениями Python и другими инструментами.

* Модуль "sqlite3" является обёрткой для библиотеки базы данных
  SQLite, предоставляя постоянное хранилище, которое можно обновлять и
  использовать со слегка нестандартным синтаксисом SQL.

* Поддержка интернационализации обеспечивается рядом модулей, включая
  "gettext", "locale", и пакетом "codecs".
